#!/usr/bin/env python3
import typing
import particles as pt
import pathlib
import auxiliary as aux
import compositions as comps
import random
#from pprint import pprint as print # debug

class Glimpse():
    """轻量级只读, 用于状态指示"""
    def __init__(self, nucleon_union: pt.NucleonUnion):
        self.name = nucleon_union.name
        self.nuc_u = nucleon_union
        self.elt_u = self.nuc_u.linked_electron_union()
        self.lastest_date = -1
        self.next_date = 0x3f3f3f3f
        self.avg_efactor = 0
        self.total_num = 0
        self.activated_num = 0
        self.is_initialized = 0
        if self.elt_u != 0:
            self.is_initialized = 1
            self.total_num = len(self.elt_u.electrons)
            for i in self.elt_u.electrons:
                if i['next_date'] > 0:
                    self.next_date = min(self.next_date, i['next_date'])
                self.lastest_date = max(self.lastest_date, i['last_date'])
                if i['is_activated']:
                    self.avg_efactor += i['efactor']
                    self.activated_num += 1
            if self.next_date == 0x3f3f3f3f:
                self.next_date = -1
                self.is_initialized = 0
            if self.activated_num == 0:
                return
            self.avg_efactor = round(self.avg_efactor / self.activated_num, 2)
        if self.next_date == 0x3f3f3f3f:
            self.next_date = -1
        return

class Apparatus():
    """反应器对象, 决策一个原子的不同记忆方式, 并反馈到布局"""
    def __init__(self, screen, reactor, atom, is_review = 0):
        self.electron: pt.Electron = atom[0]
        self.nucleon: pt.Nucleon = atom[1]
        self.positron: dict = atom[2]
        self.testdata = self.positron["testdata"]
        self.procession: typing.List[comps.Composition] = list()
        if self.positron["is_new_activation"] == 1:
            self.positron["is_new_activation"] = 0
            self.procession.append(comps.registry["recognition"](screen, reactor, atom))
            return
        for i in self.positron["testdata"].keys():
            if i == "additional_inf":
                continue
            if i == "fill_blank_test": # 加深
                self.procession.append(comps.registry[i](screen, reactor, atom))
                # self.procession.append(comps.registry[i](screen, reactor, atom))
            self.procession.append(comps.registry[i](screen, reactor, atom))
        # self.procession.reverse()
        random.shuffle(self.procession)
        if self.positron["is_new_activation"] == 0:
            self.procession.append(comps.registry['recognition'](screen, reactor, atom))
        if is_review == 1:
            self.procession = [self.procession[-2], self.procession[-1]]
    def iterator(self):
        yield from self.procession


class Reactor():
    """反应堆对象, 处理和分配一次文件记忆流程的资源与策略"""
    def __init__(self, nucleon_file: pt.NucleonUnion, electron_file: pt.ElectronUnion, screen, tasked_num):
        # 导入原子对象
        self.stage = 0
        self.nucleon_file = nucleon_file
        self.electron_file = electron_file
        self.tasked_num = tasked_num
        self.atoms_new = list()
        self.atoms_review = list()
        counter = self.tasked_num
        self.screen = screen
        self.electron_dict = electron_file.electrons_dict
        self.quality_dict = {}

        def electron_dict_get_fallback(key) -> pt.Electron:
            value = self.electron_dict.get(key)
            # 如果值不存在，则设置默认值
            if value is None:
                value = pt.Electron(key, {})  # 获取默认值
                self.electron_dict[key] = value  # 将默认值存入字典
                electron_file.sync()
            return value  # 返回获取的值（可能是默认值）

        for nucleon in nucleon_file.nucleons:
            # atom = (Electron, Nucleon, Positron) 即 (记忆元数据, 内容元数据, 运行时数据)
            atom = (electron_dict_get_fallback(nucleon.content), nucleon, {}) # 使用 "Positron" 代称 atom[2]
            atom[2]["testdata"] = nucleon_file.testdata
            atom[2]["keydata"] = nucleon_file.keydata
            if atom[0]["is_activated"] == 0:
                if counter > 0:
                    atom[2]["is_new_activation"] = 1
                    atom[0]["is_activated"] = 1
                    self.atoms_new.append(atom)
                    counter -= 1
            else:
                atom[2]["is_new_activation"] = 0
                if int(atom[0]["next_date"]) <= aux.get_daystamp():
                    atom[0]["last_date"] = aux.get_daystamp()
                    self.atoms_review.append(atom)
        # 设置运行时
        self.index: int
        self.procession: list
        self.failed: list
        self.round_title: str
        self.current_atom: typing.Tuple[pt.Electron, pt.Nucleon, dict]
        self.round_set = 0
        self.current_atom = pt.Atom.placeholder()
        #print(self.atoms_new)

    def set_round(self, title, procession):
        self.round_set = 1
        self.round_title = title
        self.procession = procession
        self.failed = list()
        self.index = -1

    def set_round_templated(self, stage):
        titles = {
            1: "复习模式",
            2: "新记忆模式",
            3: "总复习模式"
        }
        processions = {
            1: self.atoms_review,
            2: self.atoms_new,
            3: (self.atoms_new + self.atoms_review)
        }
        self.stage = stage
        ret = 1
        if stage == 1 and len(processions[1]) == 0:
            stage = 2
            ret = 2
        if stage == 1 and len(processions[2]) == 0:
            stage = 3
            ret = 3
        self.set_round(title=titles[stage], procession=processions[stage])
        return ret

    def forward(self, step = 1):
        """
        返回值规则:
        1: 重定向至 failed
        -1: 此轮已完成
        0: 下一个记忆单元
        """
        if self.index + step >= len(self.procession):
            if len(self.failed) > 0:
                self.procession = self.failed
                self.index = -1
                self.forward(step)
                if "- 额外复习" not in self.round_title:
                    self.round_title += " - 额外复习"
                self.failed = list()
                return 1 # 自动重定向到 failed
            else:
                self.round_set = 0
                return -1 # 此轮已完成
        self.index += step
        self.current_atom = self.procession[self.index]
        self.current_appar = Apparatus(self.screen, self, self.current_atom, (self.stage == 1)).iterator()
        return 0

    def save(self):
        self._deploy_report()
        print("Progress saved")
        # self.nucleon_file.save()
        if self.electron_file.total["last_date"] < aux.get_daystamp():
            self.electron_file.save()
    
    def _deploy_report(self):
        "部署所有 _report"
        for e, q in self.quality_dict.items():
            if q == -1:
                e.revisor(5, True)
                continue
            e.revisor(q)

    def report(self, atom, quality):
        "向反应器和最低质量记录汇报"
        if atom in self.atoms_new:
            self.quality_dict[atom[0]] = -1
            print(self.quality_dict)
            return
        self.quality_dict[atom[0]] = min(quality, self.quality_dict.get(atom[0], 5))
        if quality <= 3:
            self.failed.append(atom)
        print(self.quality_dict)