#!D:/IDE/anaconda3/envs/Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
@FileName：AppEventInterface.py
@Description：
@Author：XSH
@Time：2025/11/15 11:41
@Department：研发部
@Copyright：©2025 乐辰生物
"""
from PyQt5                                                  import Qt
from abc                                                    import abstractmethod
from AppInterfaces.utils                                    import *
from AppUtils import AppUtils
from AppInterfaces.ThreadPoolInterface                      import ThreadPoolInterface, PoolUtil    #
from AppInterfaces.AppEventInterfaces.AppTask               import AppTask
import numpy as np


class AppEventInterface(ThreadPoolInterface):
    @staticmethod
    def AppendTask(func, *args, **kwargs):
        if func is None:
            return
        try:
            task: AppTask = AppTask(target=func, args=args, kwargs=kwargs)
            Qt.QThreadPool.globalInstance().start(task)
        except Exception as e:
            AppUtils.print_Exception(e)

    @property
    @abstractmethod
    def isAvailable(self) -> bool:
        pass

    @abstractmethod
    def SendEvent(self, value, **args):
        pass

    def SlotClearImageListSignal(self, info, name):
        pass

    def FocusingCompleteConnect(self, callback):
        pass

    def FocusingCompleteDisconnect(self, callback):
        pass

    def SlotAppendItem(self, item):
        self.appendItem(item)

    @abstractmethod
    def StartWork(self):
        pass

    @abstractmethod
    def StopWork(self):
        pass

    @abstractmethod
    def ResetWork(self):
        pass

    @abstractmethod
    def StartFocusing(self, isShowFocusing: bool = True, **args):
        pass

    @abstractmethod
    def StopFocusing(self, isShowFocusing: bool = True, **args):
        pass

    @abstractmethod
    def appendItem(self, item, *args, **kwargs):
        pass



    @abstractmethod
    def WaitDone(self, item, *args, **kwargs):
        pass

    @abstractmethod
    def ReSet(self, **args):
        pass

    @abstractmethod
    def initPools(self):
        pass

    @abstractmethod
    def delePools(self):
        pass

    def isUpWard(self) -> int:
        return 0

    @property
    def hasIndex(self) -> bool:
        return False

    @property
    def index(self) -> int:
        return 0 if not self.hasIndex else getattr(self, 'Index', 0)

    def getMaxFocusingItem(self) -> (int, object):
        return None, None

    def deleValue(self):
        super(AppEventInterface, self).deleValue()
        if self.isValid:
            with self.condition:
                while not self.DataBuffer.empty():
                    self.DataBuffer.get()
                    self.DataBuffer.task_done()
                    Qt.QApplication.processEvents(1000)

    @abstractmethod
    def initValue(self):
        pass

    @abstractmethod
    def initConnect(self):
        pass

    @abstractmethod
    def Start(self):
        pass

    def Stop(self):
        self.deleValue()
        with self.condition:
            self.is_running = False
            self.condition.notify_all()
        if isinstance(self, Qt.QThread):
            self.quit()
        AppTimeLoop.processEvents(200)
        end_times: Qt.QDateTime = Qt.QDateTime.currentDateTime().addMSecs(500)
        while True:
            if self.is_finish:
                break
            if Qt.QDateTime.currentDateTime() > end_times:
                break
            if not self.isRunning():
                break
            AppTimeLoop.processEvents(200)

        try:
            if isinstance(self, Qt.QThread):
                if self.isRunning():
                    self.terminate()
            elif isinstance(self, threading.Thread):
                if self.is_running:
                    PoolUtil.async_raise(self.ident, SystemExit)
        except Exception as e:
            AppUtils.print_Exception(e)


    @staticmethod
    def SaveSlideModel(model: 'SlideModelInterface', image: np.ndarray, save_text: bool = False, save_yaml: bool = False):
        from AppCore.AppDBModels.DBModels import SlideModelInterface
        from AppBackEnd.ProcessManager import ImageSaveProcess, TextSaveProcess
        from AppUtils.AppDBUtils import AppDBUtils
        if not isinstance(model, SlideModelInterface):
            return
        cellfilename    , _ = AppDBUtils.save_filename  (model)
        model.SavePath       = cellfilename
        # AppTaskPool.GetInstance().submit(ImageSaveProcess, *(cellfilename, image            ), **{})
        AppEventInterface.AppendTask(ImageSaveProcess, *(cellfilename, image            ), **{})
        if save_text:
            text_filename   , _ = AppDBUtils.info_filename  (model)
            text_buffer: str    = model.to_TEXT()
            # AppTaskPool.GetInstance().submit(TextSaveProcess, *(text_filename, text_buffer  ), **{})
            AppEventInterface.AppendTask(TextSaveProcess, *(text_filename, text_buffer  ), **{})
        if save_yaml:
            text_filename, _ = AppDBUtils.info_filename(model)
            text_buffer: str = model.to_YAML()
            # AppTaskPool.GetInstance().submit(TextSaveProcess, *(text_filename, text_buffer), **{})
            AppEventInterface.AppendTask(TextSaveProcess, *(text_filename, text_buffer), **{})

    @staticmethod
    def AppendCellModel(items: list, images: list[np.ndarray]):
        from AppBackEnd.ProcessManager import AppendCellData
        AppEventInterface.AppendTask(AppendCellData, *(items, images), **{})
        # AppTaskPool.GetInstance().submit(AppendCellData, *(items, images), **{})
    @staticmethod
    def SaveImage(filename: str , image: np.ndarray):
        if not isinstance(filename, str) or len(filename) <= 0:
            return
        if not isinstance(image, np.ndarray):
            return
        from AppBackEnd.ProcessManager import ImageSaveProcess
        AppEventInterface.AppendTask(ImageSaveProcess, *(filename, image), **{})
        # AppTaskPool.GetInstance().submit(ImageSaveProcess, *(filename, image), **{})

    @staticmethod
    def SaveSpecimen(chamber_number: int, row_number: int):
        from AppBackEnd.ProcessManager import SaveSpecimenContext
        AppEventInterface.AppendTask(SaveSpecimenContext, *(chamber_number, row_number), **{})
        # AppTaskPool.GetInstance().submit(SaveSpecimenContext, *(chamber_number, row_number), **{})


    @staticmethod
    def ClearTaskPool(isWait: bool =  True):
        from AppBackEnd.BackEndEventBus.AppTaskPool import AppTaskPool
        AppTaskPool.GetInstance().shutdown(wait=isWait)
