#!D:/IDE/anaconda3/envs/Microscope_Scan python
# -*- coding: UTF-8 -*-
"""
@FileName：WebServerPool.py
@Description：
@Author：XSH
@Time：2025/11/15 11:53
@Department：研发部
@Copyright：©2025 乐辰生物
"""
import asyncio
from qasync import QEventLoop, asyncSlot
import asyncio
import sys
import threading
from PyQt5                                                  import Qt
from AppInterfaces.utils                                    import *
from AppUtils.utils                                         import *
from AppInterfaces.EventInterfaces                          import *
from AppCore.Requests                                       import *
from AppCore.Levels                                         import *
from AppInterfaces.Interfaces                               import *
from AppBackEnd.AppWebBusiness                              import *
from AppLog.logHelper import logWEBSERVER

def process_websocket_response(level: int, item: (Request, Response), manager: WebReaderInterface):
    business: WebBusinessInterface = WebAPIFactory.create(level=level, manager=manager)
    if not isinstance(business, WebBusinessInterface) or not isinstance(item, (Request, Response)):
        return
    try:
        buffer: dict = item.serialize()
        business.WaitDone(handler=item.handler, **buffer)
        logWEBSERVER << item.toJson()
    except Exception as e:
        AppUtils.print_Exception(e)

class WebServerPool(Qt.QThread, AppEventInterface, SingletonInterface):
    AppendItem      : Qt.pyqtSignal     = Qt.pyqtSignal(object)     #
    ProcessItem     : Qt.pyqtSignal     = Qt.pyqtSignal(object)     #
    _IOLocker       : Qt.QReadWriteLock = Qt.QReadWriteLock()       #
    Locker          : Qt.QMutex         = Qt.QMutex()               #
    WebSocket       : AppEventInterface                             #
    WebServer       : WebReaderInterface                            #
    @classmethod
    def GetInstance(cls, *args, **kwargs) -> 'WebServerPool':
        return super(WebServerPool, cls).GetInstance(*args, **kwargs)

    def __init__(self, parent: Qt.QObject = None):
        super(WebServerPool, self).__init__(parent=parent)
        self.Initialization('DataWebServerPool', self, parent)
        self.Mode = EventLevel.OnlyDrawMode
        self.Start()

    def initConnect(self):
        super(WebServerPool, self).initConnect()
        TYPE: Qt.Qt.ConnectionType = Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection)
        self.AppendItem.connect(slot=self.SlotAppendItem, type=TYPE)
        WebSlot.WebServerReceivedSignal.connect(slot=self.SlotAppendItem, type=Qt.Qt.ConnectionType(Qt.Qt.AutoConnection | Qt.Qt.UniqueConnection))
        self.ProcessItem.connect(slot=self.SlotProcessItem, type=TYPE)

    def initValue(self):
        super(WebServerPool, self).initValue()
        self.initPools()

    def SendEvent(self, value, **args):
        self.AppendItem.emit(value)
        AppTimeLoop.processGlobalEvents(200)

    def StartWork(self):
        self.initPools  ()
        self.Start      ()

    def StopWork(self):
        pass

    def StartFocusing(self, isShowFocusing: bool = True, **args):
        self.initPools()
        self.Start()

    def StopFocusing(self, isShowFocusing: bool = True, **args):
        pass


    def SlotProcessItem(self, item):
        from AppSettings.SystemSetting import SystemConfig
        if SystemConfig.hasAsyncioLoop:
            asyncio.run_coroutine_threadsafe(
                self.async_WaitDone( item),
                SystemConfig.async_io_loop
            )

    async def async_WaitDone(self, item, **args):
        if not self.isAvailable:
            self.initPools()
        if not isinstance(item, (Request, Response)):
            return
        try:
            business: WebBusinessInterface = WebAPIFactory.create(level=item.level, manager=self.WebServer)
            if not isinstance(business, WebBusinessInterface):
                return
            try:
                buffer: dict = item.serialize()
                await  business.async_WaitDone(handler=item.handler, **buffer)
                logWEBSERVER << item.toJson()
            except Exception as e:
                AppUtils.print_Exception(e)
        except Exception as webServerEx:
            AppUtils.print_Exception(webServerEx)

    def appendItem(self, item, *args, **kwargs):
        if not self.isRunning():
            self.is_running = True
            self.start(Qt.QThread.HighPriority)
        if isinstance(item, (Request, Response)):
            with self.condition:
                self.DataBuffer.put(item)
                self.condition.notify_all()

    def initPools(self):
        self.initWebSocket()
        self.initWebServer()

    def delePools(self):
        self.WebSocket = None
        self.WebServer = None

    def Start(self):
        if self.isRunning():
            return
        self.initPools()
        self.is_running = True
        self.start(Qt.QThread.NormalPriority)

    def run(self) -> None:
        self.process()



    def WaitDone(self, item, *args, **kwargs):
        if not self.isAvailable:
            self.initPools()
        if not isinstance(item, (Request, Response)):
            return
        try:
            self.process_websocket_response(level=item.level, item=item, manager=self.WebServer)
            # self.AppendTask(process_websocket_response, **{'level': item.level, 'item': item, 'manager': self.WebServer})
        except Exception as webServerEx:
            AppUtils.print_Exception(webServerEx)

    def process_websocket_response(self, level: int, item: (Request, Response), manager: WebReaderInterface):
        business: WebBusinessInterface = WebAPIFactory.create(level=level, manager=manager)
        if not isinstance(business, WebBusinessInterface) or not isinstance(item, (Request, Response)):
            return
        try:
            buffer: dict = item.serialize()
            business.WaitDone(handler=item.handler, **buffer)
            logWEBSERVER << item.toJson()
        except Exception as e:
            AppUtils.print_Exception(e)

    @property
    def hasWebSocket(self) -> bool:
        return hasattr(self, 'WebSocket') and isinstance(self.WebSocket, AppEventInterface)

    @property
    def hasWebServer(self) -> bool:
        return hasattr(self, 'WebServer') and isinstance(self.WebServer, WebReaderInterface)

    def initWebSocket(self):
        if not self.hasWebSocket:
            from AppBackEnd.BackEndEventBus.WebSocketPool import WebSocketPool
            self.WebSocket = WebSocketPool.GetInstance()

    def initWebServer(self):
        if not self.hasWebServer:
            from AppCore.Readers import WebReader
            self.WebServer = WebReader.GetInstance()
    def process(self):
        self.is_running = True
        self.is_finish = False
        while self.is_running:
            with self.condition:
                if not self.is_running:
                    break
                if self.DataBuffer.empty() and self.is_running:
                    self.condition.wait(0.05)
                    continue
                item = self.DataBuffer.get()
                # print("%-20s \t线程\tID:%-20s" % (self.__class__.__name__, threading.get_ident()), item)
                try:
                    # self.ProcessItem.emit(item)

                    if item is not None:
                        self.WaitDone(item)
                except Exception as e:
                    AppUtils.print_Exception(e)
                self.DataBuffer.task_done()

        self.is_running = False
        self.is_finish = True
        if isinstance(self, Qt.QThread):
            print("%-20s \t线程结束\tID:%-20s\n" % (self.__class__.__name__, self.currentThreadId().__int__()))
        elif isinstance(self, threading.Thread):
            print("%-20s \t线程结束\tID:%-20s\n" % (self.__class__.__name__, self.ident))



