#!D:\IDE\Anaconda3\envs\Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
 @Author: Administrator
 @FileName: ImplInterface.py
 @DateTime: 2025/4/8 0:28
 @SoftWare: PyCharm
 @Author  ：xsh
"""
from PyQt5 import Qt
from AppInterfaces.GlobalInterface import GlobalInterface
from abc import abstractmethod
from AppInterfaces.AppTimeLoop import AppTimeLoop
from AppInterfaces.AppFactory import AppFactory
from AppUtils.AppUtils import log_exceptions
from AppUtils import AppUtils
from AppUtils.AppConvert import AppConvert
from AppUtils.ImageUtils import ImageUtils
class ImplInterface(GlobalInterface):
    # __slots__ = ("Manager", "Parameter")

    @property
    @abstractmethod
    def hasManager(self) -> bool:
        raise Exception('Interface Instance error')

    @property
    @abstractmethod
    def hasParameter(self) -> bool:
        raise Exception('Interface Instance error')

    @property
    @abstractmethod
    def isValid(self) -> bool:
        raise Exception('Interface Instance error')

    @property
    @abstractmethod
    def IsOpen(self) -> bool:
        raise Exception('Interface Instance error')

    @property
    @abstractmethod
    def isEnabled(self) -> bool:
        raise Exception('Interface Instance error')

    @property
    @abstractmethod
    def isDisable(self) -> bool:
        raise Exception('Interface Instance error')

    @property
    @abstractmethod
    def isAvailable(self) -> bool:
        raise Exception('Interface Instance error')

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

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

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

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

    def ReOpen(self, **args) -> int:
        self.Close( **args)
        return self.Open( **args)

    @abstractmethod
    def initContext(self):
        raise Exception('Interface Instance error')


class ServerImplInterface(GlobalInterface):
    IOLocker        : Qt.QReadWriteLock = Qt.QReadWriteLock()
    Handles         : list[object]
    def initHandles(self):
        Locker: Qt.QWriteLocker = Qt.QWriteLocker(self.IOLocker)
        if not self.hasHandles:
            self.Handles = []

    def deleHandles(self):
        Locker: Qt.QWriteLocker = Qt.QWriteLocker(self.IOLocker)
        if not self.hasHandles:
            return
        while not self.isEmpty:
            value = self.Handles.pop(0)
            if value is not None:
                del value

    @property
    def hasHandles(self) -> bool:
        return isinstance(getattr(self, 'Handles', None), dict)

    @property
    def isEmpty(self) -> bool:
        return not self.hasHandles or len(self.Handles) == 0

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

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

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


    @abstractmethod
    def IsOpen(self) -> bool:
        raise Exception('Interface Instance error')

    @abstractmethod
    def isEnabled(self) -> bool:
        raise Exception('Interface Instance error')

    @abstractmethod
    def isDisable(self) -> bool:
        raise Exception('Interface Instance error')

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

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

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

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

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

    def indexOf(self, item) -> int:
        Lock: Qt.QReadLocker = Qt.QReadLocker(self.IOLocker)
        index: int = -1
        number: int = 0
        for client in self.Handles:
            if client == item:
                index = number
                break
            number += 1
        return index

    def __getitem__(self, key):
        if not self.hasHandles:
            self.initHandles()
        Locker: Qt.QReadLocker = Qt.QReadLocker(self.IOLocker)
        if isinstance(key, int) and 0 <= key < len(self.Handles):
            return self.Handles[key]
        return None

    def __setitem__(self, key, value):
        if not self.hasHandles:
            self.initHandles()
        Locker: Qt.QWriteLocker = Qt.QWriteLocker(self.IOLocker)
        if isinstance(key, int) and 0 <= key < len(self.Handles):
            old = self.Handles[key]
            if old == value:
                return
            self.Handles[key] = value
            if old is not None:
                del old
        else:
            self.Handles.append(value)




class PoolInterface(GlobalInterface):
    IOLocker        : Qt.QReadWriteLock = Qt.QReadWriteLock()
    Managers        : list[ImplInterface]
    MaxPoolLength   : int = 10
    CurrentIndex    : int = 0

    def __eq__(self, other):
        return self.isEqual(other)
    def __ne__(self, other):
        return not self.isEqual(other)

    def isEqual(self, other) -> bool:
        if isinstance(other, self.__class__):
            return other.length() == self.length() and other.currentIndex == self.currentIndex
        return False

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

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

    @property
    def maxlength(self) -> int:
        return self.MaxPoolLength

    @property
    def currentIndex(self) -> int:
        return self.CurrentIndex

    def setCurrentIndex(self, value: int):
        self.CurrentIndex = self.CurrentIndex if not isinstance(value, int) else value % self.MaxPoolLength

    @property
    def size(self) -> int:
        return 0 if not self.hasManagers else len(self.Managers)

    def length(self) -> int:
        return 0 if not self.hasManagers else len(self.Managers)

    def isEmpty(self) -> bool:
        return self.length() == 0

    def hasPool(self) -> bool:
        return self.hasManagers and self.length() == self.MaxPoolLength





    def Open(self, timeOut: int = 1000, **args) -> int:
        if not self.hasManagers:
            self.initManagers(self.Parameter if self.hasParameter else None)
        if not self.hasManagers:
            return 0
        if not self.hasPool():
            self.initPools()
        if not self.hasPool():
            return 0
        Lock: Qt.QReadLocker = Qt.QReadLocker(self.IOLocker)
        manager: ImplInterface
        for manager in self.Managers:
            if not manager:
                continue
            manager.initManager()
            manager.Open(timeOut, **args)
        return 1

    def Close(self, timeOut: int = 1000, **args) -> int:
        if not self.hasManagers:
            return 1
        Lock: Qt.QReadLocker = Qt.QReadLocker(self.IOLocker)
        manager: ImplInterface
        for manager in self.Managers:
            if not manager:
                continue
            manager.Close(timeOut, **args)
        return 1

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

    @property
    def IsOpen(self) -> bool:
        Lock: Qt.QReadLocker = Qt.QReadLocker(self.IOLocker)
        manager: ImplInterface
        for manager in self.Managers:
            if not manager:
                continue
            if not manager.IsOpen:
                return False
        return True

    @property
    def isValid(self) -> bool:
        return self.hasManagers and self.hasParameter and self.length() == self.MaxPoolLength

    @property
    def hasFront(self) -> bool:
        return isinstance(self.front, ImplInterface)

    @property
    def hasLast(self) -> bool:
        return isinstance(self.last, ImplInterface)

    @property
    def front(self) -> ImplInterface:
        return None if not self.hasManagers or self.isEmpty() else self.Managers[0]

    @property
    def last(self) -> ImplInterface:
        return None if not self.hasManagers or self.isEmpty() else self.Managers[-1]

    @property
    def handle(self) -> ImplInterface:
        try:
            self.CurrentIndex = (self.CurrentIndex + 1) % self.MaxPoolLength
            return self[self.CurrentIndex]
        except Exception as e:
            return None

    @property
    def readhandler(self) -> ImplInterface:
        try:
            self.CurrentIndex = (self.CurrentIndex + 1) % self.MaxPoolLength
            return self[self.CurrentIndex]
        except Exception as e:
            return None

    @property
    @abstractmethod
    def new_handler(self) -> ImplInterface:
        pass

    @property
    def detectorhandler(self) -> ImplInterface:
        try:
            self.CurrentIndex = (self.CurrentIndex + 1) % self.MaxPoolLength
            return self[self.CurrentIndex]
        except Exception as e:
            return None

    @property
    def slow_handler(self) -> ImplInterface:
        try:
            self.CurrentIndex = (self.CurrentIndex + 1) % self.MaxPoolLength
            return self[self.CurrentIndex]
        except Exception as e:
            return None


    @property
    def scan_handler(self) -> ImplInterface:
        try:
            self.CurrentIndex = (self.CurrentIndex + 1) % self.MaxPoolLength
            return self[self.CurrentIndex]
        except Exception as e:
            return None

    @property
    def drop_handler(self) -> ImplInterface:
        try:
            self.CurrentIndex = (self.CurrentIndex + 1) % self.MaxPoolLength
            return self[self.CurrentIndex]
        except Exception as e:
            return None

    @property
    def hook_handler(self) -> ImplInterface:
        try:
            self.CurrentIndex = (self.CurrentIndex + 1) % self.MaxPoolLength
            return self[self.CurrentIndex]
        except Exception as e:
            return None

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

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

    @property
    def parameter(self) -> object:
        return getattr(self, "Parameter", None)

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

    @abstractmethod
    def deleManagers(self):
        raise Exception('Interface Instance error')

    @abstractmethod
    def initPools(self):
        raise Exception('Interface Instance error')

    @abstractmethod
    def delePools(self):
        raise Exception('Interface Instance error')

    def indexOf(self, item) -> int:
        Lock: Qt.QReadLocker = Qt.QReadLocker(self.IOLocker)
        index: int = -1
        number: int = 0
        for client in self.Managers:
            if client == item:
                index = number
                break
            number += 1
        return index

    def __len__(self) -> int:
        return self.length()

    def __getitem__(self, key):
        if not self.hasManagers:
            self.initManagers()
        Locker: Qt.QReadLocker = Qt.QReadLocker(self.IOLocker)
        if isinstance(key, int) and 0 <= key < len(self.Managers):
            return self.Managers[key]
        return None

    def __setitem__(self, key, value):
        if not self.hasManagers:
            self.initManagers()
        Locker: Qt.QWriteLocker = Qt.QWriteLocker(self.IOLocker)
        if isinstance(key, int) and 0 <= key < len(self.Managers):
            old = self.Managers[key]
            if old == value:
                return
            self.Managers[key] = value
            if old is not None:
                del old
        else:
            self.Managers.append(value)