#!D:\IDE\Anaconda3\envs\Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
@FileName   : AsyncChamberScanningBusiness.py
@Account    : Administrator
@Time       : 2025/9/16 14:03
@Author     : xsh
@Description: 
"""
from PyQt5                                  import Qt
import asyncio
from qasync import QEventLoop, asyncSlot
from abc                                    import abstractmethod, abstractclassmethod, abstractstaticmethod
from AppInterfaces.utils                    import *
from AppSettings.utils                      import *
from AppCore.Levels                         import *
from AppCore.Managers                       import *
from AppCore.Impls                          import *
from AppCore.Requests                       import *
from AppCore.DBModels                       import *
from AppUtils.utils                         import *
from AppCore.Events                         import *
from AppBackEnd.AppEventBusBusiness         import *
from AppCore.Readers                        import *
from AppSettings.AppGlobalStatus            import AppGlobalStatus, AppStatus
from AppSettings.AppGlobalAlgorithm         import AppGlobalAlgorithm
from AppBackEnd.AppBusinessController        import AppBusinessController, AppBusinessInterface

class AsyncChamberScanningBusiness(Qt.QObject, AppBusinessController):
    Locker      : Qt.QMutex = Qt.QMutex()
    ExecuteFunction: Qt.pyqtSignal = Qt.pyqtSignal(object)
    AsyncResults: list

    def __init__(self, parent: AppBusinessInterface = None):
        super(AsyncChamberScanningBusiness, self).__init__(parent=parent if parent is not None else parent.m_Control)
        self.initialize()
        self.ScanLevel = ScanStatusLevel.Default_Status
        self.initModules(parent)

    def initModules(self, parent: AppBusinessInterface):
        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  #
            self.Process = parent.process  #
            self.HitBotConfig = parent.hitbotConfig  #
            self.CheckBusiness = parent.checkbusiness  #
            self.PickBusiness = parent.pickbusiness  #
            self.DropBusiness = parent.dropbusiness  #
            self.TrayPickBusiness = parent.traypickbusiness  #
            self.TrayDropBusiness = parent.traydropbusiness  #
            self.ScanCodeBusiness = parent.scancodebusiness  #
            self.FocusingBusiness = parent.focusingbusiness  #
            self.ScanningBusiness = parent.scanningbusiness  #
            self.OilingBusiness = parent.oilingbusiness  #
            self.CellFocusingBusiness = parent.cellfocusingBusiness  #
            # self.SlideLowScanningBusiness           = parent.slidelowscanningbusiness     #
            # self.SlideScanningBusiness              = parent.slidescanningbusiness        #
            # self.AsyncScanningBusiness              = parent.asyncscanningbusiness        #

    def initValue(self):
        super(AsyncChamberScanningBusiness, self).initValue()
        self.initAsyncResults()

    def initConnect(self):
        TYPE: Qt.Qt.ConnectionType = Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection)
        self.ExecuteFunction.connect(slot=self.execute, type=TYPE)

    @property
    def hasAsyncResults(self) -> bool:
        return hasattr(self, 'AsyncResults') and isinstance(self.AsyncResults, list)

    def initAsyncResults(self):
        if not self.hasAsyncResults:
            self.AsyncResults = []

    def deleAsyncResults(self):
        self.AsyncResults = []

    @property
    def hasResultEmpty(self) -> bool:
        return self.hasAsyncResults and len(self.AsyncResults) <= 0

    @property
    def frontResult(self) -> int:
        return None if self.hasResultEmpty else self.AsyncResults[0]


    def waitForResultNotEmpty(self, maxwaittimes: int = 50000):
        waittimes: int = max(10000, maxwaittimes)
        endtime: Qt.QDateTime = Qt.QDateTime.currentDateTime().addMSecs(waittimes)


        while True:
            if Qt.QDateTime.currentDateTime() > endtime:
                break
            if not self.hasResultEmpty:
                break
        return self.hasResultEmpty

    @asyncSlot()
    async def execute(self, function):
        if function is None:
            return
        self.initAsyncResults()
        result = await asyncio.gather(function)
        self.AsyncResults.append(result)

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

    @property
    def isAvailable(self) -> bool:
        return self.hasHitBot and self.hitbot.isAvailable

    def Done(self, ChamberNumber: int = None, *args, **kwargs):
        isWrong: int = RECODE_FAILURE
        self.status.setScanningStatus(self.ScanLevel)
        try:
            isWrong = self.waitForChamberScanning()
        except Exception as e:
            AppUtils.print_Exception(e)
        return

    def WaitDone(self, ChamberNumber: int = None, *args, **kwargs) -> int:
        isWrong: int = RECODE_FAILURE
        self.status.setScanningStatus(self.ScanLevel)
        try:
            isWrong = self.waitForChamberScanning()
        except Exception as e:
            AppUtils.print_Exception(e)
        return isWrong





    def waitForChamberScanning(self) -> int:
        isWrong: int = RECODE_FAILURE
        MinRowNumber: int
        MaxRowNumber: int
        MaxChamberNumber: int
        MinChamberNumber: int
        TrayNumber: int = 0
        TrayNumbers: list[int]
        MinChamberNumber, MaxChamberNumber = self.system.getChamberRange()
        MinRowNumber, MaxRowNumber = self.system.getRowRange()
        TrayNumbers = [ModuleLevel.ModuleTraySlide1, ModuleLevel.ModuleTraySlide2]
        chamber_number: int
        row_number: int
        tray_number: int
        """1 检测片仓玻片"""
        isWrong = self.CheckChamberSlide(chamber_number=None, isSafe=False)
        if RECODE_SUCCEED != isWrong:
            self.hitbot.moveToSafePosition()
            return isWrong
        """片仓安装状态"""
        while not self.waitForChamberAvailable():
            AppTimeLoop.processEvents(3000)
        """托盘有载玻台"""
        self.waitForClearSlideTable(TrayNumbers[0])
        self.waitForClearSlideTable(TrayNumbers[1])
        """处理停止和暂停"""
        while self.status.waitForPauseRunning():
            AppTimeLoop.processEvents(3000)
        if self.status.waitForExitRunning():
            self.sendMessage('退出扫描')
            return RECODE_SUCCEED
        chamber_number = MinChamberNumber
        row_number     = MinChamberNumber
        tray_number1    : bool
        tray_number2    : bool
        tray_model1     : SlideModelInterface
        tray_model2     : SlideModelInterface
        tray_number1, tray_number2 = self.status.getSlideTableStatus()
        tray_model1 , tray_model2  = self.status.getSlideTableModel ()
        while chamber_number <= MaxChamberNumber:
            """片仓安装状态"""
            while not self.waitForChamberAvailable():
                AppTimeLoop.processEvents(3000)
            """托盘有载玻台"""
            self.waitForClearSlideTable(TrayNumbers[0])
            self.waitForClearSlideTable(TrayNumbers[1])
            """处理停止和暂停"""
            while self.status.waitForPauseRunning():
                AppTimeLoop.processEvents(3000)
            if self.status.waitForExitRunning():
                self.sendMessage('退出扫描')
                return RECODE_SUCCEED
            while row_number <= MaxRowNumber:
                """片仓安装状态"""
                while not self.waitForChamberAvailable():
                    AppTimeLoop.processEvents(3000)
                """处理停止和暂停"""
                while self.status.waitForPauseRunning():
                    AppTimeLoop.processEvents(3000)
                if self.status.waitForExitRunning():
                    self.sendMessage('退出扫描')
                    return RECODE_SUCCEED
                tray_number1, tray_number2  = self.status.getSlideTableStatus()
                tray_model1 , tray_model2   = self.status.getSlideTableModel ()

                if not tray_number1:
                    """判断是否可以取片"""
                    isWrong = self.status.isPickAvailable(chamber_number=chamber_number, row_number=row_number)
                    if RECODE_SUCCEED == isWrong:
                        tray_number = TrayNumbers[0]
                        """片仓到载玻片"""
                        isWrong = self.SlideTableToChamber(chamber_number=chamber_number, row_number=row_number, tray_number=tray_number, isSafe=False)
                        if RECODE_SUCCEED != isWrong:
                            return isWrong
                        """处理停止和暂停"""
                        while self.status.waitForPauseRunning():
                            AppTimeLoop.processEvents(3000)
                        if self.status.waitForExitRunning():
                            self.sendMessage('退出扫描')
                            return RECODE_SUCCEED

                if not tray_number2:
                    """判断是否可以取片"""
                    isWrong = self.status.isPickAvailable(chamber_number=chamber_number, row_number=row_number)
                    if RECODE_SUCCEED == isWrong:
                        tray_number = TrayNumbers[1]
                        """片仓到载玻片"""
                        isWrong = self.SlideTableToChamber(chamber_number=chamber_number, row_number=row_number, tray_number=tray_number, isSafe=False)
                        if RECODE_SUCCEED != isWrong:
                            return isWrong
                        """处理停止和暂停"""
                        while self.status.waitForPauseRunning():
                            AppTimeLoop.processEvents(3000)
                        if self.status.waitForExitRunning():
                            self.sendMessage('退出扫描')
                            return RECODE_SUCCEED

                    """处理停止和暂停"""
                    while self.status.waitForPauseRunning():
                        AppTimeLoop.processEvents(3000)
                    if self.status.waitForExitRunning():
                        self.sendMessage('退出扫描')
                        return RECODE_SUCCEED

                """处理停止和暂停"""
                while self.status.waitForPauseRunning():
                    AppTimeLoop.processEvents(3000)
                if self.status.waitForExitRunning():
                    self.sendMessage('退出扫描')
                    return RECODE_SUCCEED
                tray_number1, tray_number2  = self.status.getSlideTableStatus   ()
                tray_model1 , tray_model2   = self.status.getSlideTableModel    ()
                if tray_model1:
                    tray_number    = tray_model1.TrayNumber
                    """玻片扫描"""
                    isWrong = self.LowScanningTraySlide(chamber_number=tray_model1.ChamberRowNumber, row_number=tray_model1.ChamberRowNumber, tray_number=tray_number, isSafe=False)

                    if RECODE_SUCCEED != isWrong:
                        return isWrong
                    """处理停止和暂停"""
                    while self.status.waitForPauseRunning():
                        AppTimeLoop.processEvents(3000)
                    if self.status.waitForExitRunning():
                        self.sendMessage('退出扫描')
                        return RECODE_SUCCEED
                    isWrong = self.SlideTableToChamber(chamber_number=tray_model1.ChamberRowNumber, row_number=tray_model1.ChamberRowNumber, tray_number=tray_number, isSafe=False)
                    if RECODE_SUCCEED != isWrong:
                        return isWrong
                    chamber_number  = tray_model1.ChamberRowNumber
                    row_number      = tray_model1.ChamberRowNumber + 1
                    if row_number > MaxRowNumber:
                        row_number = MinRowNumber
                        chamber_number = tray_model1.ChamberRowNumber + 1

                    """处理停止和暂停"""
                    while self.status.waitForPauseRunning():
                        AppTimeLoop.processEvents(3000)
                    if self.status.waitForExitRunning():
                        self.sendMessage('退出扫描')
                        return RECODE_SUCCEED
                tray_number1, tray_number2  = self.status.getSlideTableStatus   ()
                tray_model1 , tray_model2   = self.status.getSlideTableModel    ()
                if tray_model2:
                    tray_number = tray_model2.TrayNumber
                    """玻片扫描"""
                    isWrong = self.LowScanningTraySlide(chamber_number=tray_model2.ChamberRowNumber, row_number=tray_model2.ChamberRowNumber, tray_number=tray_number, isSafe=False)

                    if RECODE_SUCCEED != isWrong:
                        return isWrong
                    """处理停止和暂停"""
                    while self.status.waitForPauseRunning():
                        AppTimeLoop.processEvents(3000)
                    if self.status.waitForExitRunning():
                        self.sendMessage('退出扫描')
                        return RECODE_SUCCEED
                    isWrong = self.SlideTableToChamber(chamber_number=tray_model2.ChamberRowNumber, row_number=tray_model2.ChamberRowNumber, tray_number=tray_number, isSafe=False)
                    if RECODE_SUCCEED != isWrong:
                        return isWrong
                    chamber_number  = tray_model2.ChamberRowNumber
                    row_number      = tray_model2.ChamberRowNumber + 1
                    if row_number > MaxRowNumber:
                        row_number      = MinRowNumber
                        chamber_number  = tray_model2.ChamberRowNumber + 1

                    """处理停止和暂停"""
                    while self.status.waitForPauseRunning():
                        AppTimeLoop.processEvents(3000)
                    if self.status.waitForExitRunning():
                        self.sendMessage('退出扫描')
                        return RECODE_SUCCEED



        return RECODE_SUCCEED