import functools
import os,sys
import threading
sys.path.append(os.path.join(os.path.dirname(__file__), '..', '..'))
import thirdparty.py_trees as py_trees
from thirdparty.py_trees.trees import BehaviourTree
from core.behavior_tree import ReleaseFlowBuilder
from core.plugin import PluginManager
from core.defines import ReleasePhase, ProcessStep, ReleaseErr, Dict
from database import *
import core.logger as logger
log = logger.get_logger()

def draw_release_flow_status(snapshot_visitor, behaviour_tree):
    """保存行为树状态为HTML文件"""
    mutex = threading.Lock()
    with mutex:
        # timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        filename = f"alkaid_release_flow_status.html"
        with open(filename, 'w') as f:
            f.write('<html><head><title>SStar Alkaid Release Flow Status</title><body>')
            f.write(py_trees.display.xhtml_tree(
                behaviour_tree.root,
                show_status=True,
                visited=snapshot_visitor.visited,
                previously_visited=snapshot_visitor.visited
            ))
            f.write("</body></html>")
        filename = f"alkaid_release_flow_status.dot"
        with open(filename, 'w') as f:
            f.write(str(py_trees.display.dot_tree(behaviour_tree.root, with_blackboard_variables=True)))
    # log.info(f"Behavior tree saved to {filename}")

# 构建环境阶段 (验证配置、拉取code等基础环境的准备)
def _construct_env_phase(builder: ReleaseFlowBuilder, plugins: PluginManager):
    with builder.sequence(ReleasePhase.ENV):
        with builder.sequence(ProcessStep.PRE):
            pass
        with builder.sequence(ProcessStep.PROCESS):
            if not ReleaseOptions.SkipSyncCode:
                builder.action(plugins.BaseLine.PhaseEnv.Process())
        with builder.sequence(ProcessStep.POST):
            pass

# 配置编译文件阶段 （defconfig mkfile 等编译控制文件的配置）
def _construct_config_phase(builder: ReleaseFlowBuilder, plugins: PluginManager):
    with builder.sequence(ReleasePhase.CONFIG):
        with builder.sequence(ProcessStep.PRE):
            pass
        with builder.sequence(ProcessStep.PROCESS):
            pass
        with builder.sequence(ProcessStep.POST):
            pass

# 构建阶段(编译构建sdk，根据上一步的配置执行编译构建)
def _construct_build_phase(builder: ReleaseFlowBuilder, plugins: PluginManager):
    with builder.sequence(ReleasePhase.BUILD):
        with builder.sequence(ProcessStep.PRE):
            pass
        with builder.sequence(ProcessStep.PROCESS):
            pass
        with builder.sequence(ProcessStep.POST):
            pass

# 检查阶段（检查SDK编译结果是否符合预期）
def _construct_check_phase(builder: ReleaseFlowBuilder, plugins: PluginManager):
    with builder.sequence(ReleasePhase.CHECK):
        with builder.sequence(ProcessStep.PRE):
            pass
        with builder.sequence(ProcessStep.PROCESS):
            pass
        with builder.sequence(ProcessStep.POST):
            pass

# 打包阶段 (将SDK其他文件诸如doc，tool等打包)
def _construct_package_phase(builder: ReleaseFlowBuilder, plugins: PluginManager):
    with builder.sequence(ReleasePhase.PACKAGE):
        with builder.sequence(ProcessStep.PRE):
            pass
        with builder.sequence(ProcessStep.PROCESS):
            pass
        with builder.sequence(ProcessStep.POST):
            pass

# 验证阶段 (验证Release的SDK是否可以正常工作)
def _construct_verify_phase(builder: ReleaseFlowBuilder, plugins: PluginManager):
    with builder.sequence(ReleasePhase.VERIFY):
        with builder.sequence(ProcessStep.PRE):
            pass
        with builder.sequence(ProcessStep.PROCESS):
            pass
        with builder.sequence(ProcessStep.POST):
            pass

class ReleaseFlow():
    def __init__(self):
        # 我们的Flow默认是一个串行的流程，所以根节点用Sequence
        self.builder = ReleaseFlowBuilder()
        self.tree = None
        self.flow = None
        self.timer = None
        self.status_update_interval = 1  # 定时器间隔时间，单位秒
        self.running = False

    # 构建 Alkaid Release流程
    def construct(self, plugins: PluginManager):
        with self.builder.sequence("AlkaidReleaseFlow") as builder:
            _construct_env_phase(builder, plugins)
            _construct_config_phase(builder, plugins)
            _construct_build_phase(builder, plugins)
            _construct_check_phase(builder, plugins)
            _construct_package_phase(builder, plugins)
            _construct_verify_phase(builder, plugins)
        self.flow = self.builder.build()

    def _start_update_status(self, snapshot_visitor):
        """启动定时器"""
        if self.timer is not None:
            return

        def timer_callback():
            if self.tree is not None:
                draw_release_flow_status(snapshot_visitor, self.tree)
            # 重新设置定时器
            self.timer = threading.Timer(self.status_update_interval, timer_callback)
            self.timer.start()
        
        # 启动第一个定时器
        self.timer = threading.Timer(self.status_update_interval, timer_callback)
        self.tree.add_post_tick_handler(functools.partial(draw_release_flow_status, snapshot_visitor))
        self.timer.start()

    # 运行Release 流程
    def run(self):
        if self.flow is None:
            raise ReleaseErr("Flow is not built")
        # 使用封装好的BehaviourTree去管理流程
        self.tree = BehaviourTree(root=self.flow)
        snapshot_visitor = py_trees.visitors.SnapshotVisitor()
        self.tree.visitors.append(snapshot_visitor)
        self.tree.setup() # 初始化树
        # 启动定时器
        self._start_update_status(snapshot_visitor)
        # print(
        #     py_trees.display.dot_tree(
        #         self.tree.root
        #     )
        # )
        self.tree.tick() # 触发tick进行执行
        return self.tree.root.status

    def shutdown(self):
        if self.timer is not None:
            self.timer.cancel()
            self.timer = None
        if self.tree is not None:
            self.tree.shutdown()
