import os
import socket
import subprocess
import sys
import threading

from PyQt6.QtCore import QTimer
from PyQt6.QtWidgets import (
    QMainWindow, QWidget, QVBoxLayout, QPushButton, QTableWidget, QTableWidgetItem, QHBoxLayout, QAbstractItemView,
    QHeaderView, QProgressBar, QLabel, QMessageBox
)

from src.api.server_proxy import RenderServerProxy
from src.engines.engine_manager import EngineManager
from src.utilities.misc_helper import is_localhost, launch_url


class EngineBrowserWindow(QMainWindow):
    def __init__(self, hostname=None):
        super().__init__()
        self.delete_button = None
        self.install_button = None
        self.progress_label = None
        self.progress_bar = None
        self.table_widget = None
        self.launch_button = None
        self.hostname = hostname or socket.gethostname()
        self.setWindowTitle(f'Engine Browser ({self.hostname})')
        self.setGeometry(100, 100, 500, 300)
        self.engine_data = []
        self.initUI()
        self.init_timer()

    def initUI(self):
        # Central widget
        central_widget = QWidget()
        self.setCentralWidget(central_widget)

        # Layout
        layout = QVBoxLayout(central_widget)

        # Table
        self.table_widget = QTableWidget(0, 4)
        self.table_widget.setSelectionBehavior(QAbstractItemView.SelectionBehavior.SelectRows)
        self.table_widget.verticalHeader().setVisible(False)
        self.table_widget.itemSelectionChanged.connect(self.engine_picked)
        self.table_widget.setEditTriggers(QAbstractItemView.EditTrigger.NoEditTriggers)
        layout.addWidget(self.table_widget)
        self.update_table()

        # Progress Bar Layout
        self.progress_bar = QProgressBar()
        self.progress_bar.setMinimum(0)
        self.progress_bar.setMaximum(0)
        # self.progress_bar.setHidden(True)
        layout.addWidget(self.progress_bar)

        # Progress Bar Label
        self.progress_label = QLabel('Downloading blah blah')
        layout.addWidget(self.progress_label)

        # Buttons Layout
        buttons_layout = QHBoxLayout()

        # Install Button
        self.install_button = QPushButton('Install')
        self.install_button.clicked.connect(self.install_button_click)  # Connect to slot
        # buttons_layout.addWidget(self.install_button)

        # Launch Button
        self.launch_button = QPushButton('Launch')
        self.launch_button.clicked.connect(self.launch_button_click)  # Connect to slot
        self.launch_button.setEnabled(False)
        buttons_layout.addWidget(self.launch_button)

        #Delete Button
        self.delete_button = QPushButton('Delete')
        self.delete_button.clicked.connect(self.delete_button_click)  # Connect to slot
        self.delete_button.setEnabled(False)
        buttons_layout.addWidget(self.delete_button)

        # Add Buttons Layout to the Main Layout
        layout.addLayout(buttons_layout)

        self.update_download_status()

    def init_timer(self):
        # Set up the timer
        self.timer = QTimer(self)
        self.timer.timeout.connect(self.update_download_status)
        self.timer.start(1000)

    def update_table(self):

        def update_table_worker():
            raw_server_data = RenderServerProxy(self.hostname).get_all_engine_info()
            if not raw_server_data:
                return

            table_data = []  # convert the data into a flat list
            for _, engine_data in raw_server_data.items():
                table_data.extend(engine_data['versions'])
            self.engine_data = table_data

            self.table_widget.setRowCount(len(self.engine_data))
            self.table_widget.setColumnCount(4)

            for row, engine in enumerate(self.engine_data):
                self.table_widget.setItem(row, 0, QTableWidgetItem(engine['engine']))
                self.table_widget.setItem(row, 1, QTableWidgetItem(engine['version']))
                self.table_widget.setItem(row, 2, QTableWidgetItem(engine['type']))
                self.table_widget.setItem(row, 3, QTableWidgetItem(engine['path']))

            self.table_widget.selectRow(0)

        self.table_widget.clear()
        self.table_widget.setHorizontalHeaderLabels(['Engine', 'Version', 'Type', 'Path'])
        self.table_widget.horizontalHeader().setSectionResizeMode(0, QHeaderView.ResizeMode.Fixed)
        self.table_widget.horizontalHeader().setSectionResizeMode(1, QHeaderView.ResizeMode.Fixed)
        self.table_widget.horizontalHeader().setSectionResizeMode(2, QHeaderView.ResizeMode.Fixed)
        self.table_widget.horizontalHeader().setSectionResizeMode(3, QHeaderView.ResizeMode.Stretch)
        update_thread = threading.Thread(target=update_table_worker,)
        update_thread.start()

    def engine_picked(self):
        engine_info = self.engine_data[self.table_widget.currentRow()]
        self.delete_button.setEnabled(engine_info['type'] == 'managed')
        self.launch_button.setEnabled(is_localhost(self.hostname))

    def update_download_status(self):
        running_tasks = EngineManager.active_downloads()
        hide_progress = not bool(running_tasks)
        self.progress_bar.setHidden(hide_progress)
        self.progress_label.setHidden(hide_progress)
        # Update the status labels
        if len(running_tasks) == 0:
            new_status = ""
        elif len(running_tasks) == 1:
            task = running_tasks[0]
            new_status = f"Downloading {task.engine.capitalize()} {task.version}..."
        else:
            new_status = f"Downloading {len(running_tasks)} engines..."
        self.progress_label.setText(new_status)

    def launch_button_click(self):
        engine_info = self.engine_data[self.table_widget.currentRow()]
        launch_url(engine_info['path'])

    def install_button_click(self):
        self.update_download_status()

    def delete_button_click(self):
        engine_info = self.engine_data[self.table_widget.currentRow()]
        reply = QMessageBox.question(self, f"Delete {engine_info['engine']} {engine_info['version']}?",
                                     f"Do you want to delete {engine_info['engine']} {engine_info['version']}?",
                                     QMessageBox.StandardButton.Yes | QMessageBox.StandardButton.No)

        if reply is not QMessageBox.StandardButton.Yes:
            return

        result = RenderServerProxy(self.hostname).delete_engine(engine_info['engine'], engine_info['version'])
        if result.ok:
            self.update_table()
        else:
            QMessageBox.warning(self, f"Delete {engine_info['engine']} {engine_info['version']} Failed",
                                f"Failed to delete {engine_info['engine']} {engine_info['version']}.",
                                QMessageBox.StandardButton.Ok)
