#!D:/IDE/anaconda3/envs/Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
@FileName：ChamberDropBusiness.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 ChamberDropBusiness(Qt.QObject, AppBusinessController):
    def __init__(self, parent: AppBusinessInterface = None):
        super(ChamberDropBusiness, 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.DropChamberSlide_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) -> 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 )
            isExit          : bool  = AppConvert.ObjectConvert(args.get('isExit'          , False), bool)
            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
                elif key == 'isExit':
                    pass
                else:
                    _args[key] = args.get(key, None)
            if isinstance(chamber_number, int):
                self.ChangedScanningStatus(chamber_number, 1, self.ScanLevel)
                self.ChangedScanningStatus(chamber_number, 2, self.ScanLevel)
                self.ChangedScanningStatus(chamber_number, 3, self.ScanLevel)
                self.ChangedScanningStatus(chamber_number, 4, self.ScanLevel)
                self.ChangedScanningStatus(chamber_number, 5, self.ScanLevel)
                isWrong = self.DropChamberTray(chamber_number=chamber_number, isSafe=isSafe, isExit=isExit, **_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)
        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 )
            isExit          : bool  = AppConvert.ObjectConvert(args.get('isExit'          , False), bool)
            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
                elif key == 'isExit':
                    pass
                else:
                    _args[key] = args.get(key, None)
            if isinstance(chamber_number, int):
                self.changedTrayScanningStatus(chamber_number, self.ScanLevel, ObjectiveLevel.Objective1)
                isWrong = self.DropChamberTray(chamber_number, isSafe, isExit, **_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 DropChamberTray(self, chamber_number: int, isSafe: bool = True, isExit: bool = True, **args) -> int:
        isWrong: int = RECODE_FAILURE
        if not self.isAvailable:
            return isWrong
        MaxChamberNumber: int
        MinChamberNumber: int
        row_number      : int = self.system.MinRowNumber
        MinChamberNumber, MaxChamberNumber = self.system.getChamberRange()
        if not isinstance(chamber_number, (int, float)) or int(chamber_number) < MinChamberNumber or int(chamber_number) > MaxChamberNumber:
            return isWrong
        isWrong = self.ready_drop_chamber_tray(chamber_number)
        if RECODE_SUCCEED != isWrong:
            return isWrong
        if isExit:
            """处理扫描状态: 暂停 退出 跳过"""
            SCANNING_STATUS = self.process_scanning_status()
            if SCANNING_STATUS == RECODE_CHANGED:
                return RECODE_SUCCEED
        objective: int =  ObjectiveLevel.Objective1
        """强制退出"""
        isWrong = self.axis_h.wait_force_quit(500)
        if RECODE_SUCCEED != isWrong:
            return isWrong
        self.ChangedScanningStatus(chamber_number, row_number, self.ScanLevel, objective)
        try:
            while True:
                isWrong = self.axis_h.wait_drop_tray(chamber_number)
                if RECODE_SUCCEED == isWrong:
                    break
                self.axis_h.reset_hook()
                isWrong = self.axis_h.waitForDropTrayComplete()
                if RECODE_SUCCEED == isWrong:
                    break
                self.axis_h.wait_force_quit(500)
                self.process_scanning_warning(f"放{chamber_number}号托盘错误", True)
        except Exception as e:
            isWrong = RECODE_FAILURE
            self.process_scanning_warning(f"放{chamber_number}号托盘错误", True)
        if RECODE_SUCCEED != isWrong:
            """如果不管退出状态 则运行空挂返回"""
            self.process_scanning_warning("放托盘错误", True)
            while True:
                isWrong = self.axis_h.reset_hook()
                if RECODE_SUCCEED != isWrong:
                    isWrong = self.process_drop_warning()
                else:
                    isWrong = self.axis_h.waitForDropTrayComplete()
                if RECODE_SUCCEED == isWrong:
                    break
                self.process_scanning_warning("取托盘错误", True)
        return isWrong


    def ready_drop_chamber_tray(self, chamber_number: int):
        isWrong: int = RECODE_FAILURE
        from AppCore.AppDBModels.DBModels import ChamberConfigModel, ObjectiveModel
        if not self.isAvailable:
            return isWrong
        """判断当前载玻台是否有玻片"""
        # isWrong = self.axis_h.get_place_status()

        isWrong = self.axis_z.waitmove(0.0)
        if RECODE_SUCCEED != isWrong:
            return isWrong
        self.manipulator.reload_axis_speed()
        # isWrong = self.waitForHome_xy_microscope()
        # if RECODE_SUCCEED != isWrong:
        #     return isWrong

        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.waitmove(Objective.Safe_Limit)
        if RECODE_SUCCEED != isWrong:
            return isWrong
        isWrong = self.microscope.set_objective(objective)
        if RECODE_SUCCEED != isWrong:
            return isWrong
        isWrong = self.microscope.waitmove(z)
        return isWrong