import traceback
import sys
import subprocess

from shared.utils import Logger
from validator.validator import ValidatorApp
from updater.updater import UpdaterApp

# =============== Application ===============
class Application:
    def __init__(self):
        # Logger
        self.logger = Logger.create_logger(logger_name = "Application", log_file_name = "application")

        # App Instances
        self.validatorAppInstance: ValidatorApp | None = None
        self.updaterAppInstance: UpdaterApp | None = None
        
        # Start Validator
        self.start_validator()
        
    # ========== Validator ==========
    def start_validator(self) -> None:
        """Start the validation app."""
        try:
            self.validatorAppInstance = ValidatorApp(
                request_update = self.update_requested)
            self.validatorAppInstance.start_window()
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.start_validator.__name__}] "
                f"Failed to start the validator app. \n{traceBack}")
    
    def close_validator(self) -> None:
        """Close the validation app."""
        try:
            self.validatorAppInstance.close_window()
            self.validatorAppInstance = None
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.close_validator.__name__}] "
                f"Failed to close the validator app. \n{traceBack}")
    # ===============================
    # ========== Updater ==========
    def start_updater(self, kit_url: str) -> None:
        """Start the update app."""
        try:
            self.updaterAppInstance = UpdaterApp(update_done = self.update_done, kit_url = kit_url)
            self.updaterAppInstance.start_window()
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.start_updater.__name__}] "
                f"Failed to start the updater app. \n{traceBack}")
            
    def close_updater(self) -> None:
        """Close the update app."""
        try:
            self.updaterAppInstance.close_window()
            self.updaterAppInstance = None
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.close_updater.__name__}] "
                f"Failed to close the updater app. \n{traceBack}")
    # =============================
    
    # ========== Functionality ==========
    def update_requested(self, kit_url: str) -> None:
        """Request update to a specific validation kit version.

        Args:
            kit_version (str): The kit version to update to.
        """
        try:
            self.close_validator()
            self.start_updater(kit_url = kit_url)
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.update_requested.__name__}] "
                f"Failed to request update. \n{traceBack}")
            
    def update_done(self) -> None:
        """Signal that the update is done and restart the validator."""
        try:
            self.close_updater()
            subprocess.Popen([sys.executable])
        except:
            traceBack = traceback.format_exc()
            self.logger.error(
                f"[{self.__class__.__name__} - {self.update_done.__name__}] "
                f"Failed to close the updater and start the validator. \n{traceBack}")
    # ===================================
# ===========================================

if __name__ == "__main__":
    # Checks if the app is used in the CLI
    if len(sys.argv) > 1:
        import runpy
        from pathlib import Path
        runpy.run_path(str(Path(__file__).parent / "run_validation.py"), run_name="__main__")
    else:
        Application()