# app/runtime/collectors/excel_collector.py

import time
import threading
import pandas as pd
from datetime import datetime

from Copilot.dataAcquisition.Core.CollectedData import CollectedData
from Copilot.dataAcquisition.handlers.central_data_collector import centralDataCollector


class ExcelCollector:

    def __init__(self, file_path, data_collector: centralDataCollector):
        self.file_path = file_path
        self.data_collector = data_collector

        self._stop_event = threading.Event()
        self._thread = None

        self.df = None
        self.signals = []

    def load(self):
        import numpy as np
        self.df = pd.read_excel(
            self.file_path,
            header=None
        )

        self.signals = []

        for col in range(1, self.df.shape[1]):
            if not isinstance(self.df.iloc[0,col],str):
                break
            if np.isnan(self.df.iloc[1, col]):
                break
            self.signals.append({
                "tag": self.df.iloc[0, col],
                "interval": int(self.df.iloc[1, col]) / 1000,
                "col": col,
                "row": 2,
                "next_run": time.time()
            })

    def start(self):
        if self._thread is not None and self._thread.is_alive():
            return

        self.load()
        self._stop_event.clear()

        self._thread = threading.Thread(
            target=self.run,
            daemon=True
        )
        self._thread.start()

    def run(self):
        while not self._stop_event.is_set():
            now = time.time()

            for i,signal in enumerate(self.signals):
                if now >= signal["next_run"]:
                    value = self.df.iloc[
                        signal["row"],
                        signal["col"]
                    ]
                    if i==0:
                        print("TIME_STAMP: ", self.df.iloc[ signal["row"], 0])

                    event = CollectedData(
                        tag=signal["tag"],
                        value=float(value),
                        timestamp=datetime.utcnow()
                    )

                    self.data_collector.publish(event)

                    signal["row"] += 1

                    if signal["row"] >= self.df.shape[0]:
                        signal["row"] = 2

                    signal["next_run"] = now + signal["interval"]

            time.sleep(0.01)

    def stop(self, timeout=None):
        self._stop_event.set()

        if self._thread is not None and self._thread.is_alive():
            self._thread.join(timeout=timeout)

    def is_alive(self):
        return self._thread is not None and self._thread.is_alive()
