from queue import Queue
import threading

from Copilot.dataAcquisition.Collector.ExcelCollector import ExcelCollector
from Copilot.dataAcquisition.handlers.db_handler import DBParmsValueHandler
from Copilot.dataAcquisition.handlers.ui_handler import UIParmsValueHandler
from Copilot.dataAcquisition.handlers.central_data_collector import centralDataCollector
from Copilot.analyzer_handler import AnalyzeParmValueHandler
from Copilot.dataAcquisition.Core.eventBus import EventBus
from Copilot.SituationLayer.handlers.incident_ui_handler import UIIncidentueHandler
from Copilot.SituationLayer.handlers.incident_store import IncidentStore
from Copilot.LLMLayer.Core.LLMAnalysisRequest import LLMAnalysisRequest
from Copilot.LLMLayer.handlers.llm_analyze_request_handlers import LLMAnalyzerRequestHandler

from extensions import socketio



class copilotPipelineManager:

    def __init__(self):
        self.data_bus = EventBus()
        self.incident_bus = EventBus()
        self.llm_bus = EventBus()

        self.excel_collector = None
        self.central_collector:centralDataCollector = None
        self.data_db_handler:DBParmsValueHandler = None
        self.data_ui_handler:UIParmsValueHandler = None
        self.analyze_handler:AnalyzeParmValueHandler = None

        self.incident_ui_handler:UIIncidentueHandler = None
        self.incident_store_handler:IncidentStore = None

        self.llm_analyze_req_handler:LLMAnalyzerRequestHandler = None

        self._is_running = False
        

    
    def _rebuild_excel_collector(self,):
        excel_collector = ExcelCollector('demo-data.xlsx', self.central_collector)
        if self.excel_collector is None:
            self.excel_collector = excel_collector
        else:
            self.excel_collector.stop()
            self.excel_collector = excel_collector

    def _rebuild_central_data_collector(self,):
        central_collector = centralDataCollector(self.data_bus)
        if self.central_collector is None:
            self.central_collector = central_collector
        else:
            self.central_collector.stop()
            self.central_collector = central_collector
    
    def _rebuild_data_db_handler(self, ):
        db_handler = DBParmsValueHandler()
        if self.data_db_handler is None:
            self.data_db_handler = db_handler
        else:
            self.data_db_handler.stop()
            self.data_db_handler = db_handler

        self.data_bus.subscribe(self.data_db_handler)

    def _rebuild_data_ui_handler(self,):
        ui_handler = UIParmsValueHandler(socketio)
        if self.data_ui_handler is None:
            self.data_ui_handler = ui_handler
        else:
            self.data_ui_handler.stop()
            self.data_ui_handler = ui_handler

        self.data_bus.subscribe(self.data_ui_handler)

    def _rebuild_incident_ui_handler(self,):
        ui_handler = UIIncidentueHandler(socketio)
        if self.incident_ui_handler is None:
            self.incident_ui_handler = ui_handler
        else:
            self.incident_ui_handler.stop()
            self.incident_ui_handler = ui_handler

        self.incident_bus.subscribe(self.incident_ui_handler)

    def _rebuild_incident_store_handler(self, ):
        incident_store_handler = IncidentStore()
        if self.incident_store_handler is None:
            self.incident_store_handler = incident_store_handler
        else:
            self.incident_store_handler.stop()
            self.incident_store_handler = incident_store_handler

        self.incident_bus.subscribe(self.incident_store_handler)

    def _rebuild_analyze_handler(self,):
        analyze_handler = AnalyzeParmValueHandler(self.incident_bus)
        if self.analyze_handler is None:
            self.analyze_handler = analyze_handler
        else:
            self.analyze_handler.stop()
            self.analyze_handler = analyze_handler

        self.data_bus.subscribe(self.analyze_handler)

    def _rebuild_llm_analyze_req_handler(self,):
        llm_analyze_req_handler = LLMAnalyzerRequestHandler(socketio)
        if self.llm_analyze_req_handler is None:
            self.llm_analyze_req_handler = llm_analyze_req_handler
        else:
            self.llm_analyze_req_handler.stop()
            self.llm_analyze_req_handler = llm_analyze_req_handler

        self.llm_bus.subscribe(self.llm_analyze_req_handler)
    
    def rebuild(self,):
        self.data_bus.clear_all()
        self._rebuild_central_data_collector()
        self._rebuild_excel_collector()
        self._rebuild_data_ui_handler()
        self._rebuild_analyze_handler()
        self._rebuild_data_db_handler()
        self._rebuild_incident_store_handler()
        self._rebuild_incident_ui_handler()
        self._rebuild_llm_analyze_req_handler()
        self._is_running = False
    
    def stop(self,):
        self.central_collector.stop()
        self.excel_collector.stop()
        self.data_ui_handler.stop()
        self.data_db_handler.stop()
        self.analyze_handler.stop()
        self.incident_store_handler.stop()
        self.incident_ui_handler.stop()
        self.llm_analyze_req_handler.stop()
        self._is_running = False



    def start(self,):
        self.llm_analyze_req_handler.start()
        self.incident_ui_handler.start()
        self.incident_store_handler.start()
        self.analyze_handler.start()
        self.data_db_handler.start()
        self.data_ui_handler.start()
        self.central_collector.start()
        self.excel_collector.start()
        self._is_running = True

    def is_running(self):
        return self._is_running
    

    def request_incident_analysis( self, incident_id: str, user_message: str, user_id:int, lang='en' ):
        incident = self.incident_store_handler.load_incident(incident_id)
        if not incident:
            return False
        llm_req = LLMAnalysisRequest(incident, user_message, user_id, lang=lang)
        self.llm_bus.emit(llm_req)
        return True

        

        


