const {
    app,
    BrowserWindow,
    WebContentsView,
    BaseWindow,
    session,
    ipcMain,
    dialog,
    components,
} = require("electron");
const WebApp = require("./src/utils/WebApp");
const {
    parse_arg,
    openUrlInBrowser,
    wildCardMatchList,
} = require("./src/utils/swai_utils");
const path = require("path");
const fs = require("fs");
const Ecosystem = require("./src/utils/Ecosystem");
const os = require("os");
const { getLinuxAppIdentity } = require("./src/utils/LinuxAppIdentity");
const { ensureWidevine } = require("./src/utils/WidevineManager");
const { configureAppDataPaths } = require("./src/utils/AppDataPaths");
const { scheduleWidevineRelaunch } = require("./src/utils/AppRelaunch");

app.commandLine.appendSwitch('disk-cache-size', '104857600'); // Add 100 MB cache limit
app.commandLine.appendSwitch('enable-features', 'UseOzonePlatform'); // Enable Wayland support
app.commandLine.appendSwitch('ozone-platform-hint', 'auto'); // Auto-detect Wayland vs X11

// Import new manager classes
const LockFileManager = require("./src/managers/LockFileManager");
const WindowManager = require("./src/managers/WindowManager");
const EcosystemLauncher = require("./src/managers/EcosystemLauncher");
const EcosystemManager = require("./src/managers/EcosystemManager");
const SwaiRegistry = require("./src/managers/SwaiRegistry");

// Check for the debug mode argument
let debug_mode =
    parse_arg("--debug_mode") != null && parse_arg("--debug_mode") === "true";

let windowManager = null;
let ecosystemManager = null;
let swaiRegistry = null;
let startupWebapp = null;
let startupError = null;

// Desktop identity must be configured before Electron's ready event. Chromium
// uses it for Wayland/X11 association, Linux audio streams, and media controls.
try {
    const startupFilePath = app.isPackaged ? process.argv[1] : process.argv[2];
    if (!startupFilePath) throw new Error("No file path provided");
    if (!fs.existsSync(startupFilePath)) {
        throw new Error(`File doesn't exist: ${startupFilePath}`);
    }

    startupWebapp = WebApp.from_yaml_file(startupFilePath);
    app.setName(startupWebapp.app_name);
    process.title = startupWebapp.app_name;

    // Castlabs registers its component updater as Electron becomes ready, so
    // its persistent profile must be selected before the ready event. Changing
    // these paths later lets Widevine download but prevents the running browser
    // from registering it.
    configureAppDataPaths(
        app,
        startupWebapp.ecosystem || startupWebapp.app_id,
    );

    if (process.platform === "linux" && typeof app.setDesktopName === "function") {
        app.setDesktopName(getLinuxAppIdentity(startupWebapp.app_id).desktopName);
    }
} catch (error) {
    startupError = error;
}

app.on("window-all-closed", () => {
    app.quit();
});

app.on("ready", async () => {
    try {
        if (startupError) throw startupError;
        const webapp = startupWebapp;

        // Use ecosystem-based launching instead of app_id-based
        if (!(await EcosystemLauncher.launch(webapp))) {
            // EcosystemLauncher.launch returns false if the request was sent to an existing instance
            // In this case, we should exit this process since the app will be opened in the existing instance
            console.log("App request sent to existing ecosystem instance, exiting...");
            app.quit();
            return;
        }

        const ecosystemId = EcosystemLauncher.getEcosystemId(webapp);

        // Initialize components
        swaiRegistry = new SwaiRegistry();
        windowManager = new WindowManager(debug_mode, ecosystemId, swaiRegistry);
        windowManager.initializeDataPaths(ecosystemId);

        const widevine = await ensureWidevine(components);
        if (widevine.restartRequired) {
            try {
                // Electron's Linux relauncher keeps the replacement in the
                // terminating desktop-app scope. Start it in a fresh user
                // service after this process and its profile locks are gone.
                await scheduleWidevineRelaunch();
                console.log("[SWAI] Restarting to activate the newly installed Widevine component");
                await EcosystemLauncher.cleanup();
                app.exit(0);
                return;
            } catch (error) {
                // Do not turn an optional DRM restart into a broken first
                // launch. Widevine will be active the next time SWAI starts.
                console.warn(`[SWAI] Could not schedule the Widevine restart: ${error.message}`);
            }
        }
        
        // Initialize SwaiRegistry asynchronously before creating windows
        console.log(`Initializing SwaiRegistry for app: ${webapp.app_name}...`);
        await swaiRegistry.initialize();
        console.log('SwaiRegistry initialization complete');
        
        ecosystemManager = new EcosystemManager(windowManager, ecosystemId);
        
        // Set the ecosystem manager reference in window manager
        windowManager.setEcosystemManager(ecosystemManager);

        if (webapp.ecosystem && webapp.swai_file_path) {
            try {
                const ecosystem = Ecosystem.new_from_webapp(webapp);
                ecosystemManager.addApps(ecosystem.webapps);
            } catch (error) {
                console.warn(`Failed to preload ecosystem apps for ${webapp.ecosystem}:`, error.message);
                ecosystemManager.addApp(webapp);
            }
        } else {
            ecosystemManager.addApp(webapp);
        }

        // Create the main window
        const mainWindow = windowManager.createWindow(webapp);
        
        // Track this app in the ecosystem
        ecosystemManager.trackWindow(webapp.app_id, mainWindow);

        // Set up cleanup on app quit
        app.on('before-quit', async () => {
            if (ecosystemManager) {
                ecosystemManager.cleanup();
            }
            if (windowManager) {
                windowManager.dispose();
            }
            if (swaiRegistry) {
                await swaiRegistry.cleanup();
            }
            await EcosystemLauncher.cleanup();
        });

    } catch (error) {
        console.error("Error during app startup:", error);
        app.quit();
    }
});
