#!D:/IDE/anaconda3/envs/Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
@FileName：ScanCodeReader.py
@Description：
@Author：XSH
@Time：2025/11/12 8:57
@Department：研发部
@Copyright：©2025 乐辰生物
"""
from PyQt5 import Qt
from AppContexts.Contexts                       import SerialContext
from AppInterfaces.ImplInterfaces               import ScanCodeImplInterface
from AppInterfaces.ReaderInterfaces             import ScanCodeReaderInterface
from AppInterfaces.SingletonInterface           import SingletonInterface
from AppInterfaces.AppTimeLoop                  import AppTimeLoop
from AppUtils.AppUtils                          import AppUtils
from AppCore.AppRequestModels.SerialRequest     import SerialRequest
from AppSettings.Settings                       import (RECODE_FAILURE, RECODE_SUCCEED, SIGNAL_CONNECTION_TYPE)

class ScanCodeReader(Qt.QObject, ScanCodeReaderInterface, SingletonInterface):
    Locker: Qt.QMutex = Qt.QMutex()

    @classmethod
    def GetInstance(cls, *args, **kwargs) -> 'ScanCodeReader':
        return super(ScanCodeReader, cls).GetInstance(*args, **kwargs)

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

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

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

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

    
    def Open(self, timeOut: int = 1000, **args) -> int:
        isWrong: int = RECODE_FAILURE
        if not self.hasParameter:
            self.initContext()
        if not self.hasManager:
            self.initManager()
        if not self.hasManager:
            return isWrong
        try:
            self.Manager.Close(**args)
            self.Manager.Open(timeOut, **args)
            self.Parameter.IsOpen = self.Manager.IsOpen
        except Exception as e:
            AppUtils.print_Exception(e)
            self.Parameter.IsOpen = False
        isWrong = RECODE_SUCCEED if self.IsOpen else RECODE_FAILURE
        return isWrong


    
    def Close(self, **args) -> int:
        isWrong: int = RECODE_SUCCEED
        if not self.hasParameter:
            self.initContext()
        if not self.hasManager:
            return isWrong
        try:
            self.Manager.Close(**args)
            self.Parameter.IsOpen = self.Manager.IsOpen
        except Exception as e:
            AppUtils.print_Exception(e)
            self.Parameter.IsOpen = False
        isWrong = RECODE_SUCCEED if not self.IsOpen else RECODE_FAILURE
        return isWrong

    
    def initManager(self, **args):
        self.initContext()
        if not self.hasManager:
            from AppCore.AppImpls.ScanCodeImpl import ScanCodeImpl
            self.Manager = ScanCodeImpl(parent=self)
            self.Manager.Parameter = self.Parameter.copy()
            self.Manager.initManager(context=None)



    
    def deleManager(self, **args):
        self.initContext()
        if self.hasManager:
            try:
                self.Manager.Close()
                self.Manager.deleManager()
                del self.Manager
            except Exception as e:
                AppUtils.print_Exception(e)

        self.Manager = None


    
    def Transmit(self, **args) -> int:
        isWrong: int = RECODE_FAILURE
        buffer = args.get('buffer', None)
        if isinstance(buffer, str):
            isWrong = self.SendString(buffer, **args)
        elif isinstance(buffer, (bytes, bytearray, Qt.QByteArray)):
            isWrong = self.SendBinary(buffer, **args)
        return isWrong


    
    def Received(self, **args):
        return self.ReadBinary()


    
    def Send(self, **args) -> int:
        isWrong: int = RECODE_FAILURE
        buffer = args.get('buffer', None)
        if isinstance(buffer, str):
            isWrong = self.SendString(buffer, **args)
        elif isinstance(buffer, (bytes, bytearray, Qt.QByteArray)):
            isWrong = self.SendBinary(buffer, **args)
        return isWrong

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

    
    def WaitDone(self, **args):
        self.StartScanningCode()
        AppTimeLoop.processGlobalEvents(50)
        return self.ReadScanningCode()




    def initContext(self):
        if not self.hasParameter:
            from AppSettings.AppSetting import AppConfig, AppSetting
            self.Parameter = AppConfig.CodeScanning
        if not self.hasParameter:
            self.Parameter = SerialContext()
    
    def setHostMode(self) -> int:
        isWrong: int = RECODE_FAILURE
        if self.IsOpen:
            isWrong = self.Manager.setHostMode()
        return isWrong


    
    def getVERSION(self) -> int:
        isWrong: int = RECODE_FAILURE
        if self.IsOpen:
            isWrong = self.Manager.getVERSION()
        return isWrong

    
    def waitForScanning(self, timeout: int = 1500) -> bool:
        isWrong: int = RECODE_FAILURE
        if self.IsOpen:
            isWrong = self.Manager.waitForScanning(timeout)
        return isWrong

    def waithome(self, **args) -> int:
        self.Close()
        isWrong: int = self.Open()
        if self.IsOpen:
            self.StartScanningCode()
            self.ReadScanningCode(500)
        return isWrong

    def StartScanningCode(self) -> int:
        isWrong: int = RECODE_FAILURE
        if self.IsOpen:
            return self.Manager.StartScanningCode()
        return isWrong

    
    def StopScanningCode(self, **args) -> int:
        isWrong: int = RECODE_FAILURE
        if self.IsOpen:
            return self.Manager.StopScanningCode()
        return isWrong

    
    def ReadScanningCode(self, timeout: int = 1500) -> str:
        result: str = None
        if self.IsOpen:
            return self.Manager.ReadScanningCode(timeout)
        return result

    
    def SendString(self, buffer: str, **args) -> int:
        isWrong: int = RECODE_FAILURE
        if self.IsOpen:
            return self.Manager.SendString(buffer, **args)
        return isWrong

    
    def SendBinary(self, buffer: (bytes, bytearray, Qt.QByteArray), **args) -> int:
        isWrong: int = RECODE_FAILURE
        if self.IsOpen:
            return self.Manager.SendBinary(buffer, **args)
        return isWrong

    
    def ReadString(self, **args) -> str:
        result: str = None
        if self.IsOpen:
            return self.Manager.ReadString(**args)
        return result

    
    def ReadBinary(self) -> Qt.QByteArray:
        result: Qt.QByteArray = None
        if self.IsOpen:
            return self.Manager.ReadBinary(**args)
        return result