import dataclasses
import json
from pathlib import Path

import platformdirs

MODULE_FOLDER = Path(__file__).parent


class P:
    ASSETS = MODULE_FOLDER / 'assets'
    PYQT = MODULE_FOLDER / 'pyqt'
    DEV_PROJECT_FOLDER = MODULE_FOLDER.parent


@dataclasses.dataclass
class SoftwareConfig:
    def s(self, host, port, proto='tcp'):
        return f'{proto}://{host}:{port}'

    data_folder: Path = platformdirs.user_data_path('Flandre', 'Scarlet')
    record_folder_: Path = data_folder / 'record'
    log_folder_: Path = data_folder / 'log'
    config_folder: Path = platformdirs.user_config_path('Flandre', 'Scarlet')

    @property
    def software_config_file(self):
        return self.config_folder / 'software.json'

    @property
    def log_folder(self):
        self.log_folder_.mkdir(exist_ok=True, parents=True)
        return self.log_folder_

    @log_folder.setter
    def log_folder(self, value):
        self.log_folder_ = value

    @property
    def record_folder(self):
        self.record_folder_.mkdir(exist_ok=True, parents=True)
        return self.record_folder_

    @record_folder.setter
    def record_folder(self, value):
        self.record_folder_ = value

    @property
    def imaging_config_folder(self):
        p = self.config_folder / 'imaging'
        p.mkdir(exist_ok=True, parents=True)
        return p

    @property
    def device_config_folder(self):
        p = self.config_folder / 'device'
        p.mkdir(exist_ok=True, parents=True)
        return p

    video_height: int = 1080
    video_width: int = 960

    live_ip: str = '11.6.1.71'
    live_push_port: int = 5555
    live_rep_port: int = 5556
    device_py_rep_port: int = 5558

    @property
    def live_push_socket(self):
        return f'tcp://{self.live_ip}:{self.live_push_port}'

    @property
    def live_rep_socket(self):
        return f'tcp://{self.live_ip}:{self.live_rep_port}'

    @property
    def live_rep_socket_http(self):
        return f'http://{self.live_ip}:{self.live_rep_port}'

    @property
    def device_py_rep_socket(self):
        return f'tcp://{self.live_ip}:{self.device_py_rep_port}'

    playback_port: int = 5003

    @property
    def playback_socket(self):
        return f'tcp://127.0.0.1:{self.playback_port}'

    local_ip: str = '127.0.0.1'
    mi_rep_port: int = 5557
    muxer_rep_port: int = 5560
    driver_rep_port: int = 5561

    @property
    def mi_rep_socket(self):
        return self.s(self.local_ip, self.device_py_rep_port)

    @property
    def muxer_rep_socket(self):
        return self.s(self.local_ip, self.muxer_rep_port)

    @property
    def driver_rep_socket(self):
        return self.s(self.local_ip, self.driver_rep_port)

    switch1_ip: str = 'c1'
    switch1_token: str = '7ad51e0016e7a9d22f753d5110f76c7d'
    switch2_ip: str = 'c2'
    switch2_token: str = 'bf5a7b77a1ba3761ea63fafd8427b7d6'

    @staticmethod
    def read_config(path: Path):
        return SoftwareConfig.read_config_text(path.read_text(encoding='utf-8'))

    @staticmethod
    def read_config_text(text: str):
        j = json.loads(text)
        arg_d = dict()
        for field in dataclasses.fields(SoftwareConfig):
            try:
                v = j[field.name]
                match field.type.__name__:
                    case 'Path':
                        arg_d[field.name] = Path(v)
                    case _:
                        arg_d[field.name] = v
            except KeyError:
                pass
        sc = SoftwareConfig(**arg_d)
        return sc

    @property
    def json_text(self):
        arg_d = dict()
        for field in dataclasses.fields(SoftwareConfig):
            v = self.__getattribute__(field.name)
            match field.type.__name__:
                case 'Path':
                    arg_d[field.name] = str(v)
                case _:
                    arg_d[field.name] = v
        return json.dumps(arg_d, indent=4)

    def write_config(self, config_file=None):
        if config_file is None:
            config_file = self.software_config_file
        config_file.parent.mkdir(exist_ok=True, parents=True)
        config_file.write_text(self.json_text, encoding='utf-8')

    def copy_form(self, arg: 'SoftwareConfig'):
        for field in dataclasses.fields(SoftwareConfig):
            self.__setattr__(field.name, arg.__getattribute__(field.name))


C = SoftwareConfig()
