import configparser
import json
import os
import subprocess
from os.path import isdir, join

from PyQt5.QtCore import Qt, QSize
from PyQt5.QtWidgets import (
    QWidget, QListWidget, QListWidgetItem, QLabel, QPushButton,
    QHBoxLayout, QVBoxLayout, QMessageBox, QComboBox, QListView,
    QStyledItemDelegate, QCheckBox
)
from PyQt5.QtGui import QPixmap, QIcon
from PyQt5 import uic
from src.game_info import GameInfo
from src.game_registry import get_game_registry
from src.game_launchers import *
from src.settings import SettingsDialog
from src.update_check import UpdateCheckDialog, check_for_update
from src.populators import (
    populate_accounts_java,
    populate_versions_java,
    populate_versions_bedrock,
)

class Launcher(QWidget):
    def __init__(self, parent=None):
        super().__init__(parent)

        with open("games_config.json", "r") as f:
            self.game_configs = json.load(f)

        self.games = [
            GameInfo("Minecraft: Java Edition", "./assets/images/mcje.png", "./assets/icons/game/mcje.png"),
            GameInfo("Minecraft: Bedrock Edition", "./assets/images/mcbe.png", "./assets/icons/game/mcbe.png"),
            GameInfo("Minecraft Dungeons", "./assets/images/mcd.png", "./assets/icons/game/mcd.png"),
            GameInfo("Minecraft Legends", "./assets/images/mcl.png", "./assets/icons/game/mcl.png"),
            GameInfo("Minecraft: Story Mode", "./assets/images/mcsm.jpg", "./assets/icons/game/mcsm.png"),
            GameInfo("Minecraft Story Mode: Season 2", "./assets/images/mcsm2.jpg", "./assets/icons/game/mcsm2.png"),
            GameInfo("Minecraft: Xbox 360 Edition", "./assets/images/mc360.png", "./assets/icons/game/mc360.png"),
            GameInfo("Minecraft Classic", "./assets/images/mcc.png", "./assets/icons/game/mcc.png"),
            GameInfo("Terraria", "./assets/images/terraria.png", "./assets/icons/game/terraria.png"),
            GameInfo("Vintage Story", "./assets/images/vs.jpg", "./assets/icons/game/vs.png"),
            GameInfo("Luanti", "./assets/images/luanti.jpg", "./assets/icons/game/luanti.png"),
            GameInfo("ClassiCube", "./assets/images/classicube.jpg", "./assets/icons/game/classicube.png")
            # GameInfo("Hytale", "./assets/images/hytale.png", "./assets/icons/game/hytale.png")
        ]
        self.games = [g for g in self.games if self.game_configs.get(g.name, {}).get("show", False)]
        self.game_registry = get_game_registry(self.game_configs)

        self.load_stylesheet()

        update_available, message = check_for_update()
        
        if update_available:
            dialog = UpdateCheckDialog(message, stylesheet=self.styleSheet())
            dialog.exec_()
        else:
            print(message)

        self.current_game_index = -1
        self.setup_ui()
        self.game_list.setCurrentRow(0)

    def setup_ui(self):
        main_layout = QHBoxLayout(self)

        # Left Sidebar
        left_layout = QVBoxLayout()
        logo_row = QHBoxLayout()
        logo_label = QLabel()
        logo_pixmap = QPixmap("./assets/icons/logo.png")
        logo_label.setPixmap(logo_pixmap.scaled(28, 28, Qt.KeepAspectRatio, Qt.SmoothTransformation))
        logo_label.setFixedSize(32, 32)

        title_label = QLabel("Cuberry Launcher")
        title_label.setStyleSheet("font-size: 18px; font-weight: bold;")

        logo_row.addWidget(logo_label)
        logo_row.addWidget(title_label)
        logo_row.addStretch()

        left_layout.addLayout(logo_row)

        self.game_list = QListWidget()
        self.game_list.setFixedWidth(300)

        for game in self.games:
            item = QListWidgetItem(QIcon(game.icon_path), game.name)
            self.game_list.addItem(item)

        self.settings_button = QPushButton("Settings")
        self.settings_button.setIcon(QIcon("./assets/icons/settings.png"))
        self.settings_button.clicked.connect(self.open_settings)
        self.settings_button.setObjectName("SettingsButton")

        left_layout.addWidget(self.game_list)
        left_layout.addWidget(self.settings_button, alignment=Qt.AlignLeft)

        # Right Panel
        right_layout = QVBoxLayout()
        self.game_image = QLabel()
        self.game_image.setFixedSize(700, 394)
        self.game_image.setScaledContents(True)

        self.account_selector = QComboBox()
        self.account_selector.hide()
        account_delegate = QStyledItemDelegate()
        self.account_selector.setView(QListView())
        self.account_selector.view().setItemDelegate(account_delegate)

        self.version_selector = QComboBox()
        self.version_selector.hide()
        version_delegate = QStyledItemDelegate()
        self.version_selector.setView(QListView())
        self.version_selector.view().setItemDelegate(version_delegate)

        splitscreen = QHBoxLayout()
        self.splitscreen_checkbox = QCheckBox("Enable Splitscreen")
        self.splitscreen_checkbox.setObjectName("SplitscreenCheckbox")
        self.splitscreen_checkbox.stateChanged.connect(self.on_splitscreen_checkbox_toggled)
        self.splitscreen_account_label = QLabel("Second Account:")
        self.splitscreen_account_label.hide()
        self.splitscreen_account_selector = QComboBox()
        self.splitscreen_account_selector.hide()
        splitscreen_account_delegate = QStyledItemDelegate()
        self.splitscreen_account_selector.setView(QListView())
        self.splitscreen_account_selector.view().setItemDelegate(splitscreen_account_delegate)

        splitscreen.addWidget(self.splitscreen_checkbox)
        splitscreen.addStretch()
        splitscreen.addWidget(self.splitscreen_account_label)
        splitscreen.addWidget(self.splitscreen_account_selector)

        self.launch_button = QPushButton("Launch")
        self.launch_button.setIcon(QIcon("./assets/icons/launch.png"))
        self.launch_button.setIconSize(self.launch_button.sizeHint())

        self.open_launcher_button = QPushButton("Open Original Launcher")
        self.open_launcher_button.setIcon(QIcon("./assets/icons/open_launcher.png"))
        self.open_launcher_button.setFixedSize(190, 40)
        self.open_launcher_button.hide()
        self.open_launcher_button.clicked.connect(self.open_original_launcher)

        self.server_button = QPushButton("Server")
        self.server_button.setIcon(QIcon("./assets/icons/server.png"))
        self.server_button.setFixedSize(100, 40)
        self.server_button.hide()
        self.server_button.clicked.connect(self.on_server_clicked)

        right_layout.addWidget(self.game_image)
        right_layout.addWidget(self.version_selector)
        right_layout.addWidget(self.launch_button)
        right_layout.addStretch()
        right_layout.addLayout(splitscreen)
        right_layout.addStretch()

        bottom_right_layout = QHBoxLayout()
        bottom_right_layout.addWidget(self.account_selector, alignment=Qt.AlignLeft)
        bottom_right_layout.addStretch()
        bottom_right_layout.addWidget(self.open_launcher_button, alignment=Qt.AlignRight)
        bottom_right_layout.addWidget(self.server_button, alignment=Qt.AlignRight)
        right_layout.addLayout(bottom_right_layout)

        main_layout.addLayout(left_layout)
        main_layout.addLayout(right_layout)
        self.setLayout(main_layout)
        self.setWindowTitle("Cuberry Launcher")
        self.setFixedSize(1000, 640)
        self.load_stylesheet()
        self.game_list.currentRowChanged.connect(self.on_game_selected)
        self.launch_button.clicked.connect(self.on_launch_clicked)

    def on_game_selected(self, row):
        if not (0 <= row < len(self.games)):
            return

        game = self.games[row]
        self.current_game_index = row
        config = self.game_configs.get(game.name, {})
        pixmap = QPixmap(game.image_path)
        self.game_image.setPixmap(pixmap if not pixmap.isNull() else QPixmap())
        if pixmap.isNull():
            self.game_image.setText("No Image")

        self.account_selector.hide()
        self.version_selector.hide()
        self.open_launcher_button.hide()
        self.splitscreen_checkbox.hide()
        self.splitscreen_account_label.hide()
        self.splitscreen_account_selector.hide()
        self.splitscreen_checkbox.setChecked(False)

        if game.name == "Minecraft: Java Edition":
            instances_path = config.get("instances_path", "")
            accounts_path = os.path.join(os.path.dirname(instances_path), "accounts.json")
            self.account_selector.show()
            self.version_selector.show()
            self.splitscreen_checkbox.show()
            populate_accounts_java(self.account_selector, self.splitscreen_account_selector, accounts_path)
            populate_versions_java(self.version_selector, instances_path)
            self.open_launcher_button.show()

        elif game.name == "Minecraft: Bedrock Edition":
            self.version_selector.show()
            populate_versions_bedrock(self.version_selector)
            self.open_launcher_button.show()

        server_type = config.get("server_type")
        if server_type and server_type != "none":
            self.server_button.show()
        else:
            self.server_button.hide()

    def open_original_launcher(self):
        if self.current_game_index == -1:
            return

        game = self.games[self.current_game_index]
        config = self.game_configs.get(game.name, {})
        exec_path = config.get("exec_path", "")
        game_type = config.get("type", "native")

        if not exec_path:
            QMessageBox.warning(self, "Error", "No exec path configured.")
            return

        try:
            command = ["flatpak", "run", exec_path] if game_type == "flatpak" else [exec_path]
            subprocess.Popen(command)
        except Exception as e:
            QMessageBox.critical(self, "Launcher Error", str(e))

    def on_launch_clicked(self):
        if self.current_game_index == -1:
            return

        game = self.games[self.current_game_index]
        _, game_launcher = self.game_registry[self.current_game_index]

        print(f"Launching game: {game.name} with launcher {type(game_launcher)}")

        try:
            if isinstance(game_launcher, JavaLauncher):
                game_launcher.launch(self,
                                instance=self.version_selector.currentText(),
                                account=self.account_selector.currentText(),
                                splitscreen=self.splitscreen_checkbox.isChecked(),
                                splitscreen_account=self.splitscreen_account_selector.currentText())
            elif isinstance(game_launcher, BedrockLauncher):
                game_launcher.launch(self, profile=self.version_selector.currentText())
            elif isinstance(game_launcher, NativeLauncher):
                game_launcher.launch(self)
            elif isinstance(game_launcher, FlatpakLauncher):
                game_launcher.launch(self)
            elif isinstance(game_launcher, SteamLauncher):
                game_launcher.launch(self, steam_id=self.game_configs[game.name]["exec_path"])
            elif isinstance(game_launcher, LutrisLauncher):
                game_launcher.launch(self, lutris_id=self.game_configs[game.name]["exec_path"])
            elif isinstance(game_launcher, WebLauncher):
                game_launcher.launch(self, url="https://classic.minecraft.net")
            elif isinstance(game_launcher, Xbox360Launcher):
                game_launcher.launch(self, exec_path=self.game_configs[game.name]["exec_path"], rom_path=self.game_configs[game.name].get("rom_path"))
            else:
                raise Exception(f"Unknown launcher type: {type(game_launcher)}")
        except Exception as e:
            QMessageBox.critical(self, "Launch Error", str(e))
    

    def on_server_clicked(self):
        if self.current_game_index == -1:
            QMessageBox.warning(self, "No Game Selected", "Please select a game first.")
            return

        game = self.games[self.current_game_index]
        config = self.game_configs[game.name]
        
        server_type = config.get("server_type")
        server_exec = config.get("server_exec")

        if not server_exec:
            QMessageBox.warning(self, "Unavailable", "Server executable or URL is not configured.")
            return

        try:
            if server_type == "web":
                launcher = WebLauncher(game, config)
                launcher.launch(self, url=server_exec)
            elif server_type == "app":
                launcher = NativeLauncher(game, config)
                launcher.launch(self, exec_path=server_exec)
            else:
                QMessageBox.warning(self, "Unavailable", "No server panel or manager configured.")
        except Exception as e:
            QMessageBox.critical(self, "Server Launch Error", str(e))

    
    def on_splitscreen_checkbox_toggled(self, state):
        enabled = state == Qt.Checked
        self.splitscreen_account_label.setVisible(enabled)
        self.splitscreen_account_selector.setVisible(enabled)

    def open_settings(self):
        dlg = SettingsDialog(self)
        if dlg.exec_():
            with open("games_config.json") as f:
                self.game_configs = json.load(f)
            self.games = [g for g in self.games if self.game_configs.get(g.name, {}).get("show", False)]
            self.game_list.clear()
            for game in self.games:
                self.game_list.addItem(QListWidgetItem(QIcon(game.icon_path), game.name))
            self.game_list.setCurrentRow(0)

    def load_stylesheet(self, theme_name=None):
        if theme_name is None:
            try:
                with open("theme.txt", "r") as f:
                    theme_name = os.path.splitext(os.path.basename(f.read().strip()))[0]
            except Exception:
                theme_name = "default"

        theme_path = f"assets/ui/themes/{theme_name}.qss"
        try:
            with open(theme_path, "r") as f:
                self.setStyleSheet(f.read())
        except Exception as e:
            print(f"Failed to load stylesheet '{theme_path}': {e}")