#!D:/IDE/anaconda3/envs/Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
@FileName：CameraReaderInterface.py
@Description：
@Author：XSH
@Time：2025/11/11 15:03
@Department：研发部
@Copyright：©2025 乐辰生物
"""
from PyQt5 import Qt
import numpy as np
import cv2
from abc import abstractmethod
from AppSettings.Settings import *
from AppInterfaces.AppImplInterfaces.CameraImplInterface import CameraImplInterface, CameraContext
from AppInterfaces.ReaderInterface import ReaderInterface
from AppCore.Requests import *

class CameraReaderInterface(ReaderInterface):
    Manager     : CameraImplInterface   #
    Parameter   : CameraContext         #

    @property
    def parameter(self) -> CameraContext:
        return self.Parameter if self.hasParameter else None

    def setParameter(self, value):
        self.Parameter = value if isinstance(value, CameraContext) else None

    @property
    def hasParameter(self) -> bool:
        return hasattr(self, 'Parameter') and self.Parameter is not None and isinstance(self.Parameter, CameraContext)
    
    @property
    def hasManager(self) -> bool:
        return hasattr(self, 'Manager') and self.Manager is not None and isinstance(self.Manager, CameraImplInterface)

    @property
    def manager(self) -> CameraImplInterface:
        return None if not self.hasManager else self.Manager

    @property
    def isAvailable(self) -> bool:
        return self.hasManager and ((self.Manager.hasDevices and self.Manager.device_size > 0) or self.Manager.isAvailable)

    @property
    def isValid(self) -> bool:
        return self.hasManager and self.Manager.isValid

    @property
    def IsOpen(self) -> bool:
        return self.hasManager and self.Manager.IsOpen

    @property
    def IsGrabbing(self) -> bool:
        return self.hasManager and self.manager.IsGrabbing

    @property
    def isCorrect(self) -> bool:
        return self.hasManager and self.manager.isCorrect

    @property
    def isMono(self) -> bool:
        return self.hasManager and self.manager.isMono

    @abstractmethod
    def initColorCameraConfig(self):
        return self.hasManager and self.manager.initColorCameraConfig()

    @abstractmethod
    def Open(self, level: int = 7, timeOut: int = 1000, **args) -> int:
        raise Exception('Interface Instance error')

    @abstractmethod
    def Close(self, timeOut: int = 1000, **args) -> int:
        raise Exception('Interface Instance error')

    @abstractmethod
    def initManager(self, **args):
        raise Exception('Interface Instance error')

    @abstractmethod
    def deleManager(self, **args):
        raise Exception('Interface Instance error')


    def Transmit(self, **args) -> int:
        return RECODE_FAILURE

    
    def Received(self, **args) -> int:
        return RECODE_FAILURE

    
    def Send(self, **args) -> int:
        return RECODE_FAILURE

    
    def Read(self, **args) -> int:
        return RECODE_FAILURE

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

    def ReOpen(self , level: int = 7, timeOut: int = 1000, **args) -> int:
        self.Close(timeOut=timeOut, **args)
        return self.Open(level=level, timeOut=timeOut, **args)


    def waithome(self, **args):
        self.Close(**args)

        return self.Open(level=1)

    def waitForStopGrabbing(self, waittimes: int = 3000) -> bool:
        if self.isAvailable:
            return self.manager.waitForStopGrabbing(waittimes)
        return False

    
    def waitForClose(self, waittimes: int = 3000) -> bool:
        if self.isAvailable:
            return self.manager.waitForClose(waittimes)
        return False

    
    def waitForFindDevice(self, waittimes: int = 3000) -> bool:
        if self.isAvailable:
            return self.manager.waitForFindDevice(waittimes)
        return False

    
    def waitForDeviceOpen(self, waittimes: int = 3000) -> bool:
        if self.isAvailable:
            return self.manager.waitForDeviceOpen(waittimes)
        return False

    
    def setModel(self, level: int):
        if self.isAvailable:
            return self.manager.setModel(level)
        return None

    def changedModel(self, level: int, **args):
        if self.isAvailable:
            return self.manager.setModel(level)
        return None
    
    def setPixelParameter(self, level: int):
        if self.isAvailable:
            return self.manager.setPixelParameter(level)
        return None

    
    def changedObjective(self, level: int, timeOut: int = 1000):
        if self.isAvailable:
            return self.manager.changedObjective(level, timeOut)
        return None

    
    def StartGrabbing(self):
        if self.isAvailable:
            return self.manager.StartGrabbing()
        return None

    
    def StopGrabbing(self):
        if self.isAvailable:
            return self.manager.StopGrabbing()
        return None


    
    def GetNumpy(self, classifier: str = 'Aberration', **args) -> np.ndarray:
        if self.isAvailable:
            return self.manager.GetNumpy(classifier, **args)
        return None

    
    def StartFocusing(self, level: int, timeOut: int = 1000, **args):
        if self.isAvailable:
            return self.manager.StartFocusing(level, timeOut, **args)
        return None

    
    def StopFocusing(self):
        if self.isAvailable:
            return self.manager.StopFocusing()
        return None


    def getSlideGrabNumber(self, item, **args):
        if self.isAvailable:
            return self.manager.getSlideGrabNumber(item, **args)
        return None


    def getFocusingNumpy(self, item, classifier: str = 'Aberration', **args):
        from AppCore.DBModels import SlideModelInterface
        if self.isAvailable:
            if isinstance(item, SlideModelInterface):
                if not item.hasCamera:
                    item.initCamera()
                self.GetRequestData(item.camera, classifier, **args)
            elif isinstance(item, CameraRequest):
                self.GetRequestData(item.camera, classifier, **args)

    def getScanningNumpy(self, item, **args):
        from AppCore.DBModels import SlideModelInterface
        if self.isAvailable:
            if isinstance(item, SlideModelInterface):
                if not item.hasCamera:
                    item.initCamera()
                self.GetRequestData(item.camera, classifier=None, **args)
            elif isinstance(item, CameraRequest):
                self.GetRequestData(item, classifier=None, **args)


    def GetFocusingNumpy(self, classifier: str = 'Aberration', **args) -> np.ndarray:
        if self.isAvailable:
            return self.manager.GetFocusingNumpy(classifier, **args)
        return None

    
    def GetFocusingData(self, classifier: str = 'Aberration', **args) -> np.ndarray:
        if self.isAvailable:
            return self.manager.GetFocusingData(classifier, **args)
        return None

    
    def GetRequestData(self, request: ('CameraRequest', 'SlideModelInterface'), classifier: str = 'Aberration', **args) -> int:
        if self.isAvailable:
            return self.manager.GetRequestData(request, classifier, **args)
        return None

    
    def GetNumpyData(self, classifier: str = 'Aberration', **args) -> np.ndarray:
        if self.isAvailable:
            return self.manager.GetNumpyData(classifier, **args)
        return None

    
    def GetRequest(self, request: ('CameraRequest', 'SlideModelInterface'), classifier: str = 'Aberration', **args) -> int:
        if self.isAvailable:
            return self.manager.GetRequest(request, classifier, **args)
        return None

    
    def RequestMultiple(self, parameter: 'CameraInterface', ExposureTimes: list[int], **args) -> list[np.ndarray]:
        if self.isAvailable:
            return self.manager.RequestMultiple(parameter, ExposureTimes, **args)
        return None

    
    def RequestMultipleArray(self, parameter: 'CameraInterface', ExposureTimes: list[int], ImageArray: list[np.ndarray], **args):
        if self.isAvailable:
            return self.manager.RequestMultipleArray(parameter, ExposureTimes, ImageArray, **args)
        return None

    
    def RequestNumpy(self, parameter: 'CameraInterface', classifier: str = 'Aberration', **args) -> np.ndarray:
        if self.isAvailable:
            return self.manager.RequestNumpy(parameter, classifier, **args)
        return None

    
    def RequestMultipleImage(self, parameter: 'CameraInterface', ExposureTime: int, **args) -> np.ndarray:
        if self.isAvailable:
            return self.manager.RequestMultipleImage(parameter, ExposureTime, **args)
        return None

    
    def RequestMultipleNumpy(self, parameter: 'CameraInterface', ExposureTimes: list[int], **args) -> list[np.ndarray]:
        if self.isAvailable:
            return self.manager.RequestMultipleNumpy(parameter, ExposureTimes, **args)
        return None

    
    def RequestMultipleNumpyArray(self, parameter: 'CameraInterface', ExposureTimes: list[int], ImageArray: list[np.ndarray], **args) -> list[np.ndarray]:
        if self.isAvailable:
            return self.manager.RequestMultipleNumpyArray(parameter, ExposureTimes, ImageArray, **args)
        return None

    
    def CameraRequest(self, model: ('CameraRequest', 'SlideModelInterface'), parameter: 'CameraInterface', classifier: str = 'Aberration', **args):
        if self.isAvailable:
            return self.manager.CameraRequest(model, parameter, classifier, **args)
        return None

    
    def setGain(self, value):
        if self.isAvailable:
            return self.manager.setGain(value)
        return None

    
    def setGamma(self, value):
        if self.isAvailable:
            return self.manager.setGamma(value)
        return None

    
    def setExposureTime(self, value):
        if self.isAvailable:
            return self.manager.setExposureTime(value)
        return None

    
    def setImageROI(self, offsetX, offsetY, width, height, CenterX: bool = True, CenterY: bool = True):
        if self.isAvailable:
            return self.manager.setImageROI(offsetX, offsetY, width, height, CenterX, CenterY)
        return None

    
    def setPixelFormat(self, value):
        if self.isAvailable:
            return self.manager.setPixelFormat(value)
        return None

    
    def initCameraConfig(self):
        if self.isAvailable:
            return self.manager.initCameraConfig()
        return None

    
    def initCameraGama(self):
        if self.isAvailable:
            return self.manager.initCameraGama()
        return None

    
    def WhiteAutoOnce(self):
        if self.isAvailable:
            return self.manager.WhiteAutoOnce()
        return None