import os
import stat
import json
import asyncio


class WalletStorage:
    VERSION = 1

    def __init__(self, path=None):
        self.path = path

    def sync_read(self):
        with open(self.path, 'r') as f:
            json_data = f.read()
            json_dict = json.loads(json_data)
            if json_dict.get('version') == self.VERSION:
                return json_dict
            else:
                return self.upgrade(json_dict)

    async def read(self):
        return await asyncio.get_running_loop().run_in_executor(
            None, self.sync_read
        )

    def upgrade(self, json_dict):
        version = json_dict.pop('version', -1)
        if version == -1:
            pass
        json_dict['version'] = self.VERSION
        return json_dict

    def sync_write(self, json_dict):

        json_data = json.dumps(json_dict, indent=4, sort_keys=True)
        if self.path is None:
            return json_data

        temp_path = "{}.tmp.{}".format(self.path, os.getpid())
        with open(temp_path, "w") as f:
            f.write(json_data)
            f.flush()
            os.fsync(f.fileno())

        if os.path.exists(self.path):
            mode = os.stat(self.path).st_mode
        else:
            mode = stat.S_IREAD | stat.S_IWRITE
        try:
            os.rename(temp_path, self.path)
        except Exception:  # pylint: disable=broad-except
            os.remove(self.path)
            os.rename(temp_path, self.path)
        os.chmod(self.path, mode)

    async def write(self, json_dict):
        return await asyncio.get_running_loop().run_in_executor(
            None, self.sync_write, json_dict
        )