#!D:/IDE/anaconda3/envs/Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
@FileName：AppScanningFlow.py
@Description：
@Author：XSH
@Time：2025/11/15 12:59
@Department：研发部
@Copyright：©2025 乐辰生物
"""
import asyncio
from AppSettings.Settings import *
from PyQt5                                                      import Qt
from abc                                                        import abstractmethod, abstractclassmethod, abstractstaticmethod
from AppInterfaces.utils                                        import *
from AppCore.Levels                                             import *
from AppInterfaces.ImplInterfaces                               import *
from AppInterfaces.ReaderInterfaces                             import *
from AppUtils.utils                                             import *
from AppInterfaces.EventInterfaces                              import *
from AppInterfaces.ConfigureInterfaces                          import *
from AppBackEnd.AppBusinessController                           import AppBusinessInterface, AppBusinessController
from AppCore.Requests                                           import *
from AppBackEnd.BackEndEventBus.StatusController                import StatusController, ScanStatusController
class AppScanningFlow(Qt.QObject, AppBusinessController, SingletonInterface):
    Locker  : Qt.QMutex = Qt.QMutex()
    IOLocker: Qt.QMutex = Qt.QMutex()
    ScanLocker: Qt.QMutex = Qt.QMutex()
    DateTimer: Qt.QTimer
    ScanDataUpdateTimes: int = 1000
    @classmethod
    def GetInstance(cls, *args, **kwargs) -> 'AppScanningFlow':
        return super(AppScanningFlow, cls).GetInstance(*args, **kwargs)

    def __init__(self, parent: Qt.QObject = None):
        super(AppScanningFlow, self).__init__(parent=parent)
        self.initScanLevel()
        self.Initialization('AppScanningFlow', self, parent)

        # self.DateTimer.start()
        # self.initModules()


    def initScanLevel(self):
        self.ScanLevel = ScanStatusLevel.Default_Status
        # from AppBackEnd.BackEndEventBus.StatusController import StatusController, ScanStatusController

        # self.initDateTimer()

    def initValue(self):
        super(AppScanningFlow, self).initValue()

    def isValid(self) -> bool:
        if not self.hasGlobalStatus:
            return False
        if not self.hasSystemConfig:
            return False
        if not self.hasConfig:
            return False
        if not self.hasMotion:
            return False
        if not self.hasWebServer:
            return False
        if not self.hasEventBus:
            return False
        if not self.hasAlgorithm:
            return False
        if not self.hasFlowLocker:
            return False
        return True


    def Done(self, **args):
        isWrong: int = RECODE_FAILURE
        self.initScanLevel()
        self.status.setScanningStatus(self.ScanLevel)

        try:
            isAutoScanMode: bool = AppConvert.ObjectConvert(args.get('isAutoScanMode', True), bool)
            isWrong = self.WaitScanningFlow(isAutoScanMode=isAutoScanMode)
        except Exception as e:
            AppUtils.print_Exception(e)
        self.FlowLocker.unlock()
        self.status.setScanningStatus(ScanStatusLevel.Default_Status)
        return

    def WaitDone(self, **args) -> int:
        isWrong: int = RECODE_FAILURE

        self.initScanLevel()
        self.status.setScanningStatus(self.ScanLevel)
        try:
            isAutoScanMode: bool = AppConvert.ObjectConvert(args.get('isAutoScanMode', True), bool)
            isWrong = self.WaitScanningFlow(isAutoScanMode=isAutoScanMode)

        except Exception as e:
            AppUtils.print_Exception(e)

        return isWrong

    def initConnect(self):
        super(AppScanningFlow, self).initConnect()
        TYPE: Qt.Qt.ConnectionType = Qt.Qt.ConnectionType(Qt.Qt.UniqueConnection | Qt.Qt.AutoConnection)
        AppSlot.StartScanningSignal     .connect(slot=self.SlotStartScanningSignal  , type=TYPE)
        AppSlot.DropCurrentTraySignal   .connect(slot=self.SlotDropCurrentTraySignal, type=TYPE)
        AppSlot.DropSlideTableTraySignal.connect(slot=self.SlotDropSlideTableTraySignal , type=TYPE)
        AppSlot.ClearWarningSignal      .connect(slot=self.SlotClearWarningSignal , type=TYPE)


    def SlotClearWarningSignal(self, args: dict):
        self.clearWarning()

    def SlotDropCurrentTraySignal(self, chamber_number: int):
        Locker: Qt.QMutexLocker = Qt.QMutexLocker(self.IOLocker)
        if not HeadEndShowMode.get('DEBUG_SHOW', False):
            AppSlot.SlotDropTrayCompleteSignal.emit(Qt.QDialog.Accepted)
            return
        isWrong = self.WaitChamberDropSlide(chamber_number)
        flag: int = Qt.QDialog.Accepted if isWrong == RECODE_SUCCEED else Qt.QDialog.Rejected
        AppSlot.UiDropTrayCompleteSignal.emit(int(flag))

    def SlotDropSlideTableTraySignal(self, chamber_number: int):
        # Locker: Qt.QMutexLocker = Qt.QMutexLocker(self.IOLocker)
        try:
            isWrong = self.WaitChamberDropSlide(chamber_number)
        except Exception as e:

            AppUtils.print_Exception(e)
        self.clearWarning()
        flag: int = Qt.QDialog.Accepted
        AppSlot.UiDropTrayCompleteSignal.emit(int(flag))

    def SlotStartScanningSignal(self, parameters: dict):
        """先判断是否暂停 如果暂停 就运行 如果不是则运行流程"""
        isAutoScanMode: int = 1
        if isinstance(parameters, dict):
            isAutoScanMode = 1 if AppConvert.ObjectConvert(parameters.get('isAuto', True), bool) else 0
        self.WaitDone(isAutoScanMode=isAutoScanMode)

    def WaitScanningFlow(self, isAutoScanMode: (int, bool) = True, **args) -> int:
        if not self.status.isExit:
            return RECODE_SUCCEED
        if ScanStatusController.IsRunning:
            ScanStatusController.Stop()
        Locker: Qt.QMutexLocker = Qt.QMutexLocker(self.ScanLocker)
        self.status.setRunning(True)
        self.devices.setHeartbeat(False)
        try:
            self.initSlideScanningBusiness      ()
            self.devices.StartStatusTimer       ()
            self.webevent.SlotClearImageListSignal('changedSlide', 'changedSlide')
            isWrong = self.readyChamberScanning(isAutoScanMode)
            self.eventBus.WebSocketPushScanningData()
            if not ScanStatusController.IsRunning:
                ScanStatusController.Start()
            self.status.setJumpScanning         (False  )
            self.status.setRunning              (True   )
            if RECODE_SUCCEED == isWrong:
                isWrong = self.slidescanningbusiness.WaitDone(**args)
            self.finishChamberScanning(isWrong)
            self.webevent.SlotClearImageListSignal('changedSlide', 'changedSlide')
            if ScanStatusController.IsRunning:
                ScanStatusController.Stop()
        except Exception as e:
            AppUtils.print_Exception(e)
        finally:
            self.status.setExit(True)
            self.devices.setHeartbeat(True)
            self.eventBus.WebSocketTransmitExit()
        return RECODE_SUCCEED



    def initModules(self, parent: AppBusinessInterface = None, **args):
        self.initScanLevel                  ()
        self.initHardWare                   ()
        self.initConfig                     ()
        self.initSystemConfig               ()
        self.initGlobalStatus               ()
        self.initFlowLocker                 ()
        self.initAlgorithm                  ()
        self.initEventBus                   ()
        """实例化硬件模块和线程模块"""
        self.initDevices                    ()
        self.initEventPools                 ()
        """实例化各个业务类"""
        self.initCheckBusiness              ()
        self.initPickBusiness               ()
        self.initDropBusiness               ()
        self.initFocusingBusiness           ()
        self.initScanningBusiness           ()
        self.initOilingBusiness             ()
        self.initCellFocusingBusiness       ()
        self.initSlideScanningBusiness      ()
        self.status.setScanningStatus(self.ScanLevel)
        self.UpdateDeviceStatus()


    def initHardWare(self):
        if not self.hasHardWare:
            from AppCore.AppManagers.HardWareManager import HardWareManager
            self.HardWare = HardWareManager.GetInstance()


    def initApplication(self):
        self.Application = None


    def initAlgorithm(self):
        if not self.hasAlgorithm:
            from AppSettings.AppGlobalAlgorithm import AppGlobalAlgorithm
            self.Algorithm = AppGlobalAlgorithm.GetInstance()

    def initEventBus(self):
        if not self.hasEventBus:
            from AppBackEnd.BackEndEventBus.AppEventBusPool import AppEventBusPool
            self.EventBus = AppEventBusPool.GetInstance()



    def initCheckBusiness(self):
        if not self.hasCheckBusiness:
            from AppBackEnd.BackEndBusiness.ChamberCheckBusiness import ChamberCheckBusiness
            self.CheckBusiness = ChamberCheckBusiness(self)


    def initPickBusiness(self):
        if not self.hasPickBusiness:
            from AppBackEnd.BackEndBusiness.ChamberPickBusiness import ChamberPickBusiness
            self.PickBusiness = ChamberPickBusiness(self)


    def initDropBusiness(self):
        if not self.hasDropBusiness:
            from AppBackEnd.BackEndBusiness.ChamberDropBusiness import ChamberDropBusiness
            self.DropBusiness = ChamberDropBusiness(self)


    def initFocusingBusiness(self):
        if not self.hasFocusingBusiness:
            from AppBackEnd.BackEndBusiness.SlideFocusingBusiness import SlideFocusingBusiness
            self.FocusingBusiness = SlideFocusingBusiness(self)


    def initScanningBusiness(self):

        if not self.hasScanningBusiness:
            from AppBackEnd.BackEndBusiness.SlideScanningBusiness import SlideScanningBusiness
            self.ScanningBusiness = SlideScanningBusiness(self)


    def initOilingBusiness(self):
        if not self.hasOilingBusiness:
            from AppBackEnd.BackEndBusiness.SlideOilingBusiness import SlideOilingBusiness
            self.OilingBusiness = SlideOilingBusiness(self)


    def initCellFocusingBusiness(self):
        if not self.hasCellFocusingBusiness:
            from AppBackEnd.BackEndBusiness.SlideCellFocusingBusiness import SlideCellFocusingBusiness
            self.CellFocusingBusiness = SlideCellFocusingBusiness(self)



    def initSlideScanningBusiness(self):
        if not self.hasSlideScanningBusiness:
            from AppBackEnd.BackEndBusiness.ChamberScanningBusiness import ChamberScanningBusiness
            self.SlideScanningBusiness = ChamberScanningBusiness(self)


    # @property
    # def hasDateTimer(self) -> bool:
    #     return hasattr(self, 'DateTimer') and isinstance(self.DateTimer, Qt.QTimer)
    #
    # def initDateTimer(self):
    #     if not self.hasDateTimer:
    #         TYPE: Qt.Qt.ConnectionType = Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection)
    #         self.DateTimer = Qt.QTimer(self)
    #         self.DateTimer.setInterval(self.ScanDataUpdateTimes)
    #         self.DateTimer.timeout.connect(self.UpdateScanningDateTime, TYPE)
    #
    # def UpdateScanningDateTime(self):
    #     ScanStatusController.SendEvent(Request.APIInstance(WebAPILevel.getScanningData))