import dearpygui.dearpygui as dpg
from datetime import datetime
import threading
import subprocess
from datos.Config import ConfigManager

config = ConfigManager()

class Output:
    _instances = {}

    def __new__(cls, name):
        if name not in cls._instances:
            cls._instances[name] = super(Output, cls).__new__(cls)
        return cls._instances[name]

    def __init__(self, name):
        self.name = name
        self.tag = name + "_output"
        self.output = ""
        self.tag_text = self.tag + "_text"
        self.thread = None  # Variable para almacenar el hilo de lectura de salida

    def main_view(self):
        with dpg.window(label=self.name, width=config.SCREEN_WIDTH*0.40, height=config.SCREEN_HEIGHT*0.97, show=True, tag=self.tag,
                        pos=(config.SCREEN_WIDTH*0.59, 0)):
            with dpg.child_window(width=config.SCREEN_WIDTH*0.39, height=config.SCREEN_HEIGHT*0.9, show=True, tag=self.tag_text):
                dpg.add_text(default_value=self.output, wrap=-1, tag=self.tag_text + "_inner_text")
            dpg.bind_item_font(self.tag_text, "min_font")

    def clear_output(self):
        self.output = ""
        dpg.set_value(self.tag_text + "_inner_text", self.output)

    def set_output(self, output):
        timestamp = datetime.now().strftime("[%d-%m-%Y %H:%M:%S]")
        self.output += f"{timestamp} {output}\n"
        dpg.set_value(self.tag_text + "_inner_text", self.output)
        self.scroll_to_end()

    def scroll_to_end(self):
        dpg.set_y_scroll(self.tag_text, dpg.get_y_scroll_max(self.tag_text))

    def delete_view(self):
        dpg.delete_item(self.tag)

    def read_process_output(self):
        while True:
            try:
                output = self.thread.stdout.readline().strip()
            except ValueError:
                return "Error in read_process_output"

            if output:
                self.set_output(output)
            elif self.thread.poll() is not None:  # Verifica si el proceso ha terminado
                break

    def init_process(self, process):
        try:
            self.clear_output()  # Limpiar la salida anterior
            self.thread = subprocess.Popen(process, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, cwd=config.DIR_ACT)

            # Iniciar el hilo de lectura de salida
            output_thread = threading.Thread(target=self.read_process_output)
            output_thread.start()

            # Esperar a que el proceso termine
            exit_code = self.thread.wait()
            self.thread = None  # Restablecer el hilo a None
            return 0

        except Exception as e:
            return -1

    @classmethod
    def hide_all_except(cls, instance_name):
        if instance_name not in cls._instances:
            raise ValueError(f"No existe una instancia con el nombre '{instance_name}'")

        for name, instance in cls._instances.items():
            if name == instance_name:
                if dpg.does_item_exist(instance.tag):
                    dpg.show_item(instance.tag)
            else:
                if dpg.does_item_exist(instance.tag):
                    dpg.hide_item(instance.tag)

    @classmethod
    def get_instance(cls, name):
        return cls._instances.get(name)
