#!D:/IDE/anaconda3/envs/Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
@FileName：ChamberCheckBusiness.py
@Description：
@Author：XSH
@Time：2025/11/15 13:04
@Department：研发部
@Copyright：©2025 乐辰生物
"""
import asyncio
import copy
from AppSettings.Settings import *
from PyQt5                                                      import Qt
from abc                                                        import abstractmethod, abstractclassmethod, abstractstaticmethod
from AppInterfaces.utils                                        import *
from AppUtils.utils                                             import *
from AppCore.Levels                                             import *
from AppCore.DBModels                                           import *
from AppInterfaces.Interfaces                                   import *
from AppCore.Requests                                           import *
from AppBackEnd.AppBusinessController                           import AppBusinessController, AppBusinessInterface
class ChamberCheckBusiness(Qt.QObject, AppBusinessController):
    CheckTimer: Qt.QTimer
    def __init__(self, parent: AppBusinessInterface = None):
        super(ChamberCheckBusiness, self).__init__(parent=parent if parent is not None else parent.m_Control)
        self.initialize()
        self.initScanLevel()
        self.initModules(parent)


    def initScanLevel(self):
        self.ScanLevel = ScanStatusLevel.Check_Status

    def initModules(self, parent: AppBusinessInterface = None, **args):
        if isinstance(parent, AppBusinessInterface):
            self.Config                             = parent.config                       #
            self.SystemConfig                       = parent.system                       #
            self.HardWare                           = parent.devices                      #
            self.GlobalStatus                       = parent.status                       #
            self.Application                        = parent.application                  #
            self.Algorithm                          = parent.algorithm                    #
            self.EventBus                           = parent.eventBus                     #

    def isValid(self) -> bool:
        return self.hasGlobalStatus and self.hasSystemConfig and self.hasConfig and self.hasDetector and self.hasMotion

    @property
    def isAvailable(self) -> bool:
        return self.isValid() and self.hasAxisX and self.hasAxisY and self.hasAxisZ and self.hasMicroscope and self.hasAxisH


    def Done(self, **args):
        isWrong: int = RECODE_FAILURE
        self.status.setScanningStatus(self.ScanLevel)
        self.devices.setHeartbeat(False)
        try:
            isSafe          : bool  = AppConvert.ObjectConvert(args.get('isSafe'          , True), bool)
            chamber_number  : int   = AppConvert.ObjectConvert(args.get('chamber_number'  , None), int )
            row_number      : int   = AppConvert.ObjectConvert(args.get('row_number'      , None), int )
            tray_number     : int   = AppConvert.ObjectConvert(args.get('tray_number'     , None), int )
            keys: list[str] = list(args.keys())
            _args: dict = {}
            for key in keys:
                if key == 'isSafe':
                    pass
                elif key == 'chamber_number':
                    pass
                elif key == 'row_number':
                    pass
                elif key == 'tray_number':
                    pass
                else:
                    _args[key] = args.get(key, None)
            if isinstance(chamber_number, int):
                isWrong = self.CheckChamber(chamber_number=chamber_number, isSafe=isSafe, **_args)
            else:
                isWrong = self.CheckAll(isSafe=isSafe, **_args)
        except Exception as e:
            AppUtils.print_Exception(e)
        self.devices.setHeartbeat(True)
        if self.status.isExit:
            self.status.setScanningStatus(ScanStatusLevel.FinishScanning_Status)
        elif self.status.isJumpScanning:
            self.status.setScanningStatus(ScanStatusLevel.JumpScanning_Status)
        elif RECODE_SUCCEED == isWrong:
            self.status.setScanningStatus(self.ScanLevel)
        elif not ScanStatusLevel.isHitBotWarning(self.status.scanning_level):
            self.status.setScanningStatus(ScanStatusLevel.Check_Warning_Status)
        self.eventBus.WebSocketPushScanningData()
        return

    def WaitDone(self, **args) -> int:
        isWrong: int = RECODE_FAILURE
        self.status.setScanningStatus(self.ScanLevel)

        self.devices.setHeartbeat(False)
        try:
            isSafe          : bool  = AppConvert.ObjectConvert(args.get('isSafe'          , True), bool)
            chamber_number  : int   = AppConvert.ObjectConvert(args.get('chamber_number'  , None), int )
            row_number      : int   = AppConvert.ObjectConvert(args.get('row_number'      , None), int )
            tray_number     : int   = AppConvert.ObjectConvert(args.get('tray_number'     , None), int )
            keys: list[str] = list(args.keys())
            _args: dict = {}
            for key in keys:
                if key == 'isSafe':
                    pass
                elif key == 'chamber_number':
                    pass
                elif key == 'row_number':
                    pass
                elif key == 'tray_number':
                    pass
                else:
                    _args[key] = args.get(key, None)
            if isinstance(chamber_number, int):
                self.changedTrayScanningStatus(chamber_number, self.ScanLevel ,ObjectiveLevel.Objective1)
                isWrong = self.CheckChamber(chamber_number=chamber_number, isSafe=isSafe, **_args)
            else:
                isWrong = self.CheckAll(isSafe=isSafe, **_args)
        except Exception as e:
            AppUtils.print_Exception(e)

        if self.status.isExit:
            self.status.setScanningStatus(ScanStatusLevel.FinishScanning_Status)
        elif self.status.isJumpScanning:
            self.status.setScanningStatus(ScanStatusLevel.JumpScanning_Status)
        elif RECODE_SUCCEED == isWrong:
            self.status.setScanningStatus(self.ScanLevel)
        self.eventBus.WebSocketPushScanningData()
        return isWrong

    def CheckChamber(self, chamber_number: int, isSafe: bool = False, **args) -> int:
        isWrong: int = RECODE_FAILURE
        MaxChamberNumber: int
        MinChamberNumber: int
        MinChamberNumber, MaxChamberNumber = self.system.getChamberRange()
        if isinstance(chamber_number, int) and MinChamberNumber <= chamber_number <= MaxChamberNumber:
            pass
        else:
            return isWrong
        if not self.isAvailable:
            return isWrong

        isWrong = self.ready_check_chamber()
        if RECODE_SUCCEED != isWrong:
            return isWrong
        """处理扫描状态: 暂停 退出 跳过"""
        SCANNING_STATUS = self.process_scanning_status()
        if SCANNING_STATUS == RECODE_CHANGED:
            return RECODE_SUCCEED
        """初始化当前状态"""
        self.status.InitTrayStatus(chamber_number)
        """强制退出"""
        isWrong = self.axis_h.wait_force_quit(500)
        """处理扫描状态: 暂停 退出 跳过"""
        SCANNING_STATUS = self.process_scanning_status()
        if SCANNING_STATUS == RECODE_CHANGED:
            return RECODE_SUCCEED
        if RECODE_SUCCEED != isWrong:
            return isWrong
        isWrong = self.axis_h.wait_check_tray(chamber_number)
        self.initCheckTimer()
        self.check_timer.start()
        status: int = 0
        if RECODE_SUCCEED == isWrong:
            status = self.axis_h.get_layer_detector_status(chamber_number)
        else:
            self.axis_h.set_h_force_quit()
        self.status.SetTrayDetectorStatus(chamber_number, status)
        self.webserverevent.SendEvent(Request.APIInstance(WebAPILevel.getChamberStatus))
        self.finish_check_chamber()
        self.axis_h.wait_force_quit(500)
        self.check_timer.stop()
        return isWrong


    def CheckAll(self, isSafe: bool = True, **args) -> int:
        isWrong: int = RECODE_FAILURE
        if not self.isAvailable:
            return isWrong
        MaxChamberNumber: int
        MinChamberNumber: int
        MinChamberNumber, MaxChamberNumber = self.system.getChamberRange()
        chamber_number  : int
        isWrong = self.ready_check_chamber()
        if RECODE_SUCCEED != isWrong:
            return isWrong
        self.status.InitChamberStatus()
        """处理扫描状态: 暂停 退出 跳过"""
        SCANNING_STATUS = self.process_scanning_status()
        if SCANNING_STATUS == RECODE_CHANGED:
            return RECODE_SUCCEED

        """强制退出"""
        self.axis_h.wait_force_quit(500)
        if RECODE_SUCCEED != isWrong:
            return isWrong
        """处理扫描状态: 暂停 退出 跳过"""
        SCANNING_STATUS = self.process_scanning_status()
        if SCANNING_STATUS == RECODE_CHANGED:
            return RECODE_SUCCEED
        isWrong = self.axis_h.wait_check_chamber()
        status  : list[int] = [0] * MaxChamberNumber
        if RECODE_SUCCEED == isWrong:
            status = self.axis_h.get_layer_status()
        else:
            self.axis_h.set_h_force_quit()
        self.status.SetChamberDetectorStatus(status)
        self.webserverevent.SendEvent(Request.APIInstance(WebAPILevel.getChamberStatus))

        self.finish_check_chamber()

        return isWrong


    def finish_check_chamber(self):
        isWrong: int = RECODE_FAILURE
        if not self.isAvailable:
            return isWrong
        self.axis_h.wait_force_quit(None)
        isWrong = self.axis_z.waitmove(0.0)
        return isWrong

    def ready_check_chamber(self) -> int:
        isWrong: int = RECODE_FAILURE
        if not self.isAvailable:
            return isWrong
        isWrong = self.axis_z.waitmove(0.0)
        if RECODE_SUCCEED != isWrong:
            return isWrong
        isWrong = self.devices.waitForDeviceHome()

        if RECODE_SUCCEED != isWrong:
            return isWrong
        from AppCore.AppDBModels.DBModels import ChamberConfigModel, ObjectiveModel
        x: float
        y: float
        z: float
        objective: int = ObjectiveLevel.Objective1
        x, y, z = ChamberConfigModel.getCheckPosition_xyz()
        Objective: ObjectiveModel = ObjectiveModel.getConfig(objective)
        self.microscope.init_z_range()
        self.microscope.set_z_speed(Objective.Default_Speed)
        isWrong = self.microscope.set_objective(objective)
        if RECODE_SUCCEED != isWrong:
            return isWrong
        isWrong = self.microscope.waitmove(z)
        if RECODE_SUCCEED != isWrong:
            return isWrong


        if RECODE_SUCCEED != isWrong:
            return isWrong

        isWrong = self.manipulator.waitmove_xy(x, y)
        return isWrong


    @property
    def hasCheckTimer(self) -> bool:
        return hasattr(self, 'CheckTimer') and isinstance(self.CheckTimer, Qt.QTimer)


    @property
    def check_timer(self) -> Qt.QTimer:
        self.initCheckTimer()
        return self.CheckTimer if self.hasCheckTimer else None


    def initCheckTimer(self):
        if not self.hasCheckTimer:
            self.CheckTimer = Qt.QTimer()
            self.CheckTimer.setInterval(1000)
            TYPE: Qt.Qt.ConnectionType = Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection)
            self.CheckTimer.timeout.connect(self.SlotCheckTimer, TYPE)

    def SlotCheckTimer(self):

        status: list[int] = [0] * MaxChamberNumber
        if self.isAvailable:
            status = self.axis_h.get_layer_status_()
        self.status.SetChamberDetectorStatus(status)
        self.webserverevent.SendEvent(Request.APIInstance(WebAPILevel.getChamberStatus))