import pathlib
import toml
import time
import auxiliary as aux


class Electron:
    """电子: 记忆分析元数据及算法"""
    algorithm = "SM-2"  # 暂时使用 SM-2 算法进行记忆拟合, 考虑 SM-15 替代

    def __init__(self, content: str, metadata: dict):
        self.content = content
        self.metadata = metadata
        if metadata == {}:
            # print("NULL")
            self._default_init()

    def _default_init(self):
        defaults = {
            'efactor': 2.5,  # 易度系数, 越大越简单, 最大为5
            'real_rept': 0,  # (实际)重复次数
            'rept': 0,  # (有效)重复次数
            'interval': 0,  # 最佳间隔
            'last_date': 0,  # 上一次复习的时间戳
            'next_date': 0,  # 将要复习的时间戳
            'is_activated': 0,  # 激活状态
            # *NOTE: 此处"时间戳"是以天为单位的整数, 即 UNIX 时间戳除以一天的秒数取整
            'last_modify': time.time()  # 最后修改时间戳(此处是UNIX时间戳)
        }
        self.metadata = defaults

    def activate(self):
        self.metadata['is_activated'] = 1
        self.metadata['last_modify'] = time.time()

    def modify(self, var: str, value):
        if var in self.metadata:
            self.metadata[var] = value
            self.metadata['last_modify'] = time.time()
        else:
            print(f"警告: '{var}' 非已知元数据字段")

    def revisor(self, quality: int = 5, is_new_activation: bool = False):
        """SM-2 算法迭代决策机制实现
        根据 quality(0 ~ 5) 进行参数迭代最佳间隔
        quality 由主程序评估

        Args:
            quality (int): 记忆保留率量化参数
        """
        print(f"REVISOR: {quality}, {is_new_activation}")
        if quality == -1:
            return -1

        self.metadata['efactor'] = self.metadata['efactor'] + (
            0.1 - (5 - quality) * (0.08 + (5 - quality) * 0.02)
        )
        self.metadata['efactor'] = max(1.3, self.metadata['efactor'])

        if quality < 3:
            # 若保留率低于 3，重置重复次数
            self.metadata['rept'] = 0
            self.metadata['interval'] = 0  # 设为0，以便下面重新计算 I(1)
        else:
            self.metadata['rept'] += 1

        self.metadata['real_rept'] += 1

        if is_new_activation:  # 初次激活
            self.metadata['rept'] = 0
            self.metadata['efactor'] = 2.5

        if self.metadata['rept'] == 0:  # 刚被重置或初次激活后复习
            self.metadata['interval'] = 1  # I(1)
        elif self.metadata['rept'] == 1:
            self.metadata['interval'] = 6  # I(2) 经验公式
        else:
            self.metadata['interval'] = round(
                self.metadata['interval'] * self.metadata['efactor']
            )

        self.metadata['last_date'] = aux.get_daystamp()
        self.metadata['next_date'] = aux.get_daystamp() + self.metadata['interval']
        self.metadata['last_modify'] = time.time()

    def __str__(self):
        return (
            f"记忆单元预览 \n"
            f"内容: '{self.content}' \n"
            f"易度系数: {self.metadata['efactor']:.2f} \n"
            f"已经重复的次数: {self.metadata['rept']} \n"
            f"下次间隔: {self.metadata['interval']} 天 \n"
            f"下次复习日期时间戳: {self.metadata['next_date']}"
        )

    def __eq__(self, other):
        if self.content == other.content:
            return True
        return False

    def __hash__(self):
        return hash(self.content)

    def __getitem__(self, key):
        if key == "content":
            return self.content
        if key in self.metadata:
            return self.metadata[key]
        else:
            raise KeyError(f"Key '{key}' not found in metadata.")

    def __setitem__(self, key, value):
        if key == "content":
            raise AttributeError("content 应为只读")
        self.metadata[key] = value
        self.metadata['last_modify'] = time.time()

    def __iter__(self):
        yield from self.metadata.keys()

    def __len__(self):
        return len(self.metadata)

    @staticmethod
    def placeholder():
        return Electron("电子对象样例内容", {})


class Nucleon:
    """核子: 材料元数据"""

    def __init__(self, content: str, data: dict):
        self.metadata = data
        self.content = content

    def __getitem__(self, key):
        if key == "content":
            return self.content
        if key in self.metadata:
            return self.metadata[key]
        else:
            raise KeyError(f"Key '{key}' not found in metadata.")

    def __iter__(self):
        yield from self.metadata.keys()

    def __len__(self):
        return len(self.metadata)

    def __hash__(self):
        return hash(self.content)

    @staticmethod
    def placeholder():
        return Nucleon("核子对象样例内容", {})


class NucleonUnion:
    """
    替代原有 NucleonFile 类, 支持复杂逻辑

    Attributes:
        path (Path): 对应于 NucleonUnion 实例的文件路径。
        name (str): 核联对象的显示名称，从文件名中派生。
        nucleons (list): 内部核子对象的列表。
        nucleons_dict (dict): 内部核子对象的字典，以核子内容作为键。
        keydata (dict): 核子对象字典键名的翻译。
        testdata (dict): 记忆测试项目的元数据。

    Parameters:
        path (Path): 包含核子数据的文件路径。
    """

    def __init__(self, path):
        self.path = path
        self.name = path.name.replace(path.suffix, "")
        with open(path, 'r') as f:
            all = toml.load(f)
            lst = list()
            for i in all.keys():
                if "data" in i:
                    continue
                lst.append(Nucleon(i, all[i]))
            self.keydata = all["keydata"]
            self.testdata = all["testdata"]
            self.nucleons = lst
            self.nucleons_dict = {i.content: i for i in lst}

    def __len__(self):
        return len(self.nucleons)

    def save(self):
        with open(self.path, 'w') as f:
            tmp = {i.content: i.metadata for i in self.nucleons}
            toml.dump(tmp, f)


class ElectronUnion:
    """取代原有 ElectronFile 类, 以支持复杂逻辑"""

    def __init__(self, path):
        self.path = path
        self.name = path.name.replace(path.suffix, "")
        with open(path, 'r') as f:
            all = toml.load(f)
            lst = list()
            for i in all.keys():
                lst.append(Electron(i, all[i]))
            self.electrons = lst
            self.electrons_dict = {i.content: i for i in lst}

    def sync(self):
        """同步 electrons_dict 中新增对到 electrons 中"""
        self.electrons = self.electrons_dict.values()

    def save(self):
        # print(1)
        with open(self.path, 'w') as f:
            tmp = {i.content: i.metadata for i in self.electrons}
            # print(tmp)
            toml.dump(tmp, f)


"""
class AtomicFile():
    def __init__(self, path, type_="unknown"):
        self.path = path
        self.type_ = type_
        if type_ == "nucleon":
            self.name, self.datalist = Nucleon.import_from_file(pathlib.Path(path))
        if type_ == "electron":
            self.name, self.datalist = Electron.import_from_file(pathlib.Path(path))
    def save(self):
        dictobj = {i.content: i.export_data() for i in self.datalist}
        print(dictobj)
        if self.type_ == "nucleon":
            Nucleon.save_to_file(dictobj, self.path)
        if self.type_ == "electron":
            Electron.save_to_file(dictobj, self.path)
    def get_full_content(self):
        if self.type_ == "nucleon":
            text = ""
            for i in self.datalist:
                text += i.content
            return text
        return ""
    def get_len(self):
        return len(self.datalist)
"""


class Atom:
    @staticmethod
    def placeholder():
        return (Electron.placeholder(), Nucleon.placeholder(), {})

    @staticmethod
    def advanced_placeholder():
        return (
            Electron("两只黄鹤鸣翠柳", {}),
            Nucleon(
                "两只黄鹤鸣翠柳",
                {
                    "note": [],
                    "translation": "臣子李密陈言：我因命运不好，小时候遭遇到了不幸",
                    "keyword_note": {
                        "险衅": "凶险祸患（这里指命运不好）",
                        "夙": "早时，这里指年幼的时候",
                        "闵": "通'悯'，指可忧患的事",
                        "凶": "不幸，指丧父"
                    }
                }
            ),
            {
                "keydata": {
                    "note": "笔记",
                    "keyword_note": "关键词翻译",
                    "translation": "语句翻译"
                },
                "testdata": {
                    "additional_inf": ["translation", "note", "keyword_note"],
                    "fill_blank_test": ["translation"],
                    "draw_card_test": ["keyword_note"]
                },
                "is_new_activation": 0
            }
        )