#!D:\IDE\Anaconda3\envs\Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
 @Author: Administrator
 @FileName: AppGlobalAlgorithm.py
 @DateTime: 2025/5/28 16:38
 @SoftWare: PyCharm
 @Author  ：xsh
"""
from PyQt5 import Qt
import asyncio
from qasync import QEventLoop, asyncSlot
from AppCore.Levels import *
from AppCore.Requests import *
from AppSettings.Settings import *
from AppInterfaces.utils import *
from AppInterfaces.ManagerInterface                                 import ManagerInterface            #
from AppInterfaces.SingletonInterface                               import SingletonInterface          #
from AppCore.AppAlgorithms.SurfaceFitting                           import SurfaceFitting              #
from AppCore.AppAlgorithms.YOLODetectorModel                        import YOLODetectorModel           #
from AppCore.AppAlgorithms.ObbDetectorModel                         import ObbDetectorModel            #
from AppCore.AppAlgorithms.SlidePointUtils                          import SlidePointUtils             #
from AppCore.AppDBModels.WeightModels.PreviewClassifierModel        import PreviewClassifierModel      #
from AppCore.AppDBModels.WeightModels.CollectClassifierModel        import CollectClassifierModel      #
from AppCore.AppDBModels.WeightModels.WeightModelInterface          import WeightModelInterface        #
from AppUtils.AppDBUtils                                            import AppDBUtils
from AppUtils.ImageUtils                                            import ImageUtils
from AppUtils.AppUtils                                              import AppUtils
from AppCore.AppDBModels.SlideModels.CellModel                      import CellModel
from AppCore.AppDBModels.SlideModels.SlideScanningModel             import SlideScanningModel
from AppCore.AppDBModels.SlideModels.SlideLoggerModel               import SlideLoggerModel
from AppCore.AppDBModels.SlideModels.AllCellModel                   import AllCellModel
from AppInterfaces.Interfaces import AlgorithmManagerInterface
class AppGlobalAlgorithm(Qt.QObject, AlgorithmManagerInterface, SingletonInterface):
    Locker: Qt.QMutex = Qt.QMutex()
    @classmethod
    def GetInstance(cls, *args, **kwargs) -> 'AppGlobalAlgorithm':
        return super(AppGlobalAlgorithm, cls).GetInstance(*args, **kwargs)

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


    def isValid(self) -> bool:
        return self.hasScanSurface

    def initValue(self):
        super(AppGlobalAlgorithm, self).initValue()
        self.initScanSurface()






    def initConnect(self):
        super(AppGlobalAlgorithm, self).initConnect()

    def initPreviewClassifier   (self):
        if self.hasPreviewClassifier:
            return
        # 细胞识别模型 责任链 模式
        Classifiers: list[str] = PreviewClassifierModel.Classifiers()
        models: list[YOLODetectorModel] = []
        self.PreviewClassifier = YOLODetectorModel(level=Classifiers[0], next_model=None, parent=self)
        for index, name in enumerate(Classifiers):
            if index == 0:
                pass
            else:
                models.append(YOLODetectorModel(level=name, next_model=None, parent=self.PreviewClassifier))
        header: YOLODetectorModel = self.PreviewClassifier
        for model in models:
            header.NextModel = model
            model.LastModel = header
            header = model

    def initCollectClassifier   (self):
        if self.hasCollectClassifier:
            return
            # 细胞识别模型 责任链 模式
        Classifiers: list[str] = CollectClassifierModel.Classifiers()
        models: list[ObbDetectorModel] = []
        self.CollectClassifier = ObbDetectorModel(level=Classifiers[0], parent=self)
        for index, name in enumerate(Classifiers):
            if index == 0:
                pass
            else:
                if self.isMicronucleus(name):
                    pass
                else:
                    models.append(ObbDetectorModel(level=name, parent=self.CollectClassifier))
        header: ObbDetectorModel = self.CollectClassifier
        for model in models:
            header.NextModel = model
            model.LastModel = header
            header = model

    def delePreviewClassifier   (self):
        if not self.hasPreviewClassifier:
            return
        if not self.hasCollectClassifier:
            return

        try:
            models: list[YOLODetectorModel] = []
            Classifier: YOLODetectorModel = self.PreviewClassifier
            while True:
                if Classifier is None:
                    break
                models.append(Classifier)
                Classifier = Classifier.NextModel

            for Classifier in models:
                if Classifier is not None:
                    Classifier.unloadModel()
                    Classifier.deleteLater()
        except Exception as e:
            pass
        self.PreviewClassifier = None

    def deleCollectClassifier   (self):
        if not self.hasCollectClassifier:
            return
        try:
            models: list[ObbDetectorModel] = []
            Classifier: ObbDetectorModel = self.CollectClassifier
            while True:
                if Classifier is None:
                    break
                models.append(Classifier)
                Classifier = Classifier.NextModel

            for Classifier in models:
                if Classifier is not None:
                    Classifier.unloadModel()
                    Classifier.deleteLater()
        except Exception as e:
            pass
        self.CollectClassifier = None




    def initScanSurface(self):
        if not self.hasScanSurface:
            self.ScanSurface = SurfaceFitting()



    @staticmethod
    def SlideFocusingArray(left: int, top: int, width: int, height: int, max_row: int, max_col: int, focus_rows: int, focus_cols: int, re_row_col: bool = False) -> list[list[int]]:
        return SlidePointUtils.SlideFocusingPoints(left, top, width, height, max_row, max_col, focus_rows, focus_cols, re_row_col)

    @staticmethod
    def SlideOilDropingArray(left: int, top: int, width: int, height: int, max_row: int, max_col: int, drop_rows: int, drop_cols: int) -> list[list[int]]:
        return SlidePointUtils.SlideOilDropingPoints(left, top, width, height, max_row, max_col, drop_rows, drop_cols)

    @staticmethod
    def SlideAnointingArray(left: int, top: int, width: int, height: int, max_row: int, max_col: int, drop_rows: int, drop_cols: int) -> (list, list):
        return SlidePointUtils.SlideAnointingPoints(left, top, width, height, max_row, max_col, drop_rows, drop_cols)

    @staticmethod
    def SlideScanningArray(begin_row: int, begin_col: int, row_number: int, col_number: int, max_row: int, max_col: int, is_row_s_line: bool = True) -> list[list[int]]:
        return SlidePointUtils.SlideScanningPoints(begin_row, begin_col, row_number, col_number, max_row, max_col, is_row_s_line)

    @staticmethod
    def MicronucleusScanningArray(begin_row: int, begin_col: int, row_number: int, col_number: int, max_row: int, max_col: int, focus_rows: int, focus_cols: int) -> list[list[int]]:
        return SlidePointUtils.MicronucleusScanningArray(begin_row, begin_col, row_number, col_number, max_row, max_col, focus_rows, focus_cols)



    @staticmethod
    def getOilPointCount(width: int, height: int) -> int:
        OilDropingNumber: int = 2
        if 1 <= height <= 10:
            OilDropingNumber = 2
        elif 10 < height <= 25:
            OilDropingNumber = 3
        elif 25 < height <= 40:
            OilDropingNumber = 4
        else:
            OilDropingNumber = 5
        return OilDropingNumber

    @staticmethod
    def getAnointingPointCount(width: int, height: int) -> (int, int):
        AnointingRowNumber: int = 3
        AnointingColNumber: int = 3
        if 1 <= width <= 10:
            AnointingRowNumber = 2
        elif 10 < width <= 15:
            AnointingRowNumber = 3
        else:
            AnointingRowNumber = 4

        if 1 <= height <= 10:
            AnointingColNumber = 3
        elif 10 < height <= 25:
            AnointingColNumber = 4
        elif 25 < height <= 40:
            AnointingColNumber = 5
        else:
            AnointingColNumber = 6
        return AnointingRowNumber, AnointingColNumber
