"use strict";
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
    var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
    if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
    else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
    return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
var __metadata = (this && this.__metadata) || function (k, v) {
    if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var __param = (this && this.__param) || function (paramIndex, decorator) {
    return function (target, key) { decorator(target, key, paramIndex); }
};
var FileOpenManager_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileOpenManager = void 0;
const fs = __importStar(require("fs/promises"));
const path = __importStar(require("path"));
const tsyringe_1 = require("tsyringe");
const package_manager_1 = require("../package-manager");
const process_manager_1 = require("../process-manager");
const view_manager_1 = require("../view-manager");
const filesystem_1 = require("../filesystem");
const ipc_1 = require("../ipc");
const FileOpenHandler_1 = require("./FileOpenHandler");
/**
 * FileOpenManager
 *
 * Manages file type associations and handles opening files with appropriate applications.
 */
let FileOpenManager = class FileOpenManager extends ipc_1.EdenEmitter {
    static { FileOpenManager_1 = this; }
    packageManager;
    processManager;
    viewManager;
    fsManager;
    userDirectory;
    preferencesPath;
    fileOpenHandler;
    // Built-in default extension -> app ID mappings
    defaultRegistry = new Map();
    // User override preferences (extension -> app ID)
    userPreferences = new Map();
    // Special key for directories
    static DIRECTORY_KEY = "__directory__";
    constructor(userDirectory, packageManager, processManager, viewManager, fsManager, ipcBridge, commandRegistry) {
        super(ipcBridge);
        this.packageManager = packageManager;
        this.processManager = processManager;
        this.viewManager = viewManager;
        this.fsManager = fsManager;
        this.userDirectory = userDirectory;
        this.preferencesPath = path.join(userDirectory, "file-associations.json");
        this.initializeDefaultRegistry();
        // Create and register handler
        this.fileOpenHandler = new FileOpenHandler_1.FileOpenHandler(this);
        commandRegistry.registerManager(this.fileOpenHandler);
    }
    /**
     * Initialize with user preferences loaded from disk
     */
    async initialize() {
        await this.loadUserPreferences();
        console.log(`FileOpenManager initialized with ${this.userPreferences.size} user preferences`);
    }
    /**
     * Set up built-in default handlers
     */
    initializeDefaultRegistry() {
        // Directories open in file manager
        this.defaultRegistry.set(FileOpenManager_1.DIRECTORY_KEY, "com.eden.files");
        // Text files - open in text editor
        const textExtensions = [
            "txt",
            "md",
            "markdown",
            "log",
            "json",
            "xml",
            "yaml",
            "yml",
            "toml",
            "js",
            "jsx",
            "mjs",
            "cjs",
            "ts",
            "tsx",
            "mts",
            "cts",
            "css",
            "scss",
            "sass",
            "less",
            "html",
            "htm",
            "ini",
            "cfg",
            "conf",
            "env",
            "py",
            "rs",
            "go",
            "java",
            "c",
            "cpp",
            "h",
            "hpp",
            "sh",
            "bash",
            "zsh",
            "fish",
        ];
        for (const ext of textExtensions) {
            this.defaultRegistry.set(ext, "com.eden.editor");
        }
        // Image files
        const imageExtensions = [
            "png",
            "jpg",
            "jpeg",
            "gif",
            "webp",
            "svg",
            "bmp",
            "ico",
        ];
        for (const ext of imageExtensions) {
            this.defaultRegistry.set(ext, "com.eden.files"); // Fallback to file manager for now
        }
        // Eden packages
        this.defaultRegistry.set("edenite", "com.eden.files"); // Could be a package installer
    }
    /**
     * Load user preferences from disk
     */
    async loadUserPreferences() {
        try {
            const content = await fs.readFile(this.preferencesPath, "utf-8");
            const prefs = JSON.parse(content);
            this.userPreferences = new Map(Object.entries(prefs));
        }
        catch {
            // File doesn't exist or is invalid, start with empty preferences
            this.userPreferences = new Map();
        }
    }
    /**
     * Save user preferences to disk
     */
    async saveUserPreferences() {
        const prefs = Object.fromEntries(this.userPreferences);
        await fs.mkdir(path.dirname(this.preferencesPath), { recursive: true });
        await fs.writeFile(this.preferencesPath, JSON.stringify(prefs, null, 2));
    }
    /**
     * Get the file extension from a path (lowercase, without dot)
     */
    getExtension(filePath) {
        const ext = path.extname(filePath).toLowerCase();
        return ext.startsWith(".") ? ext.slice(1) : ext;
    }
    /**
     * Get the handler app ID for a file path
     */
    getHandler(filePath, isDirectory = false) {
        const key = isDirectory
            ? FileOpenManager_1.DIRECTORY_KEY
            : this.getExtension(filePath);
        // User preference takes priority
        if (this.userPreferences.has(key)) {
            return this.userPreferences.get(key);
        }
        // Fall back to default registry
        return this.defaultRegistry.get(key);
    }
    /**
     * Get handler for a specific extension
     */
    getHandlerForExtension(extension) {
        const ext = extension.toLowerCase().replace(/^\./, "");
        // User preference takes priority
        if (this.userPreferences.has(ext)) {
            return this.userPreferences.get(ext);
        }
        // Fall back to default registry
        return this.defaultRegistry.get(ext);
    }
    /**
     * Set user preference for a file extension
     */
    async setDefaultHandler(extension, appId) {
        const ext = extension.toLowerCase().replace(/^\./, "");
        this.userPreferences.set(ext, appId);
        await this.saveUserPreferences();
    }
    /**
     * Remove user preference for a file extension (revert to default)
     */
    async removeDefaultHandler(extension) {
        const ext = extension.toLowerCase().replace(/^\./, "");
        this.userPreferences.delete(ext);
        await this.saveUserPreferences();
    }
    /**
     * Get all apps that can handle a specific extension
     */
    getSupportedHandlers(extension) {
        const ext = extension.toLowerCase().replace(/^\./, "");
        const handlers = [];
        // Check all installed apps for file handlers
        const apps = this.packageManager.getInstalledApps();
        for (const app of apps) {
            if (app.fileHandlers) {
                for (const handler of app.fileHandlers) {
                    if (handler.extensions.map((e) => e.toLowerCase()).includes(ext)) {
                        handlers.push({
                            appId: app.id,
                            appName: app.name,
                            handlerName: handler.name,
                            icon: handler.icon || app.icon,
                        });
                    }
                }
            }
        }
        // Also add default handler if it exists and isn't already in the list
        const defaultHandler = this.defaultRegistry.get(ext);
        if (defaultHandler && !handlers.some((h) => h.appId === defaultHandler)) {
            const app = this.packageManager.getAppManifest(defaultHandler);
            if (app) {
                handlers.push({
                    appId: app.id,
                    appName: app.name,
                });
            }
        }
        return handlers;
    }
    /**
     * Get all file type associations
     */
    getAllAssociations() {
        const result = {};
        // Add all default registry entries
        for (const [ext, appId] of this.defaultRegistry) {
            result[ext] = {
                default: appId,
                userOverride: this.userPreferences.get(ext),
            };
        }
        // Add any user preferences that aren't in default registry
        for (const [ext, appId] of this.userPreferences) {
            if (!result[ext]) {
                result[ext] = {
                    default: undefined,
                    userOverride: appId,
                };
            }
        }
        return result;
    }
    /**
     * Open a file with its default handler
     */
    async openFile(filePath) {
        try {
            // Resolve masked path to full filesystem path
            const fullPath = this.fsManager.resolvePath(filePath);
            const stats = await fs.stat(fullPath);
            const isDirectory = stats.isDirectory();
            // Get handler
            const handlerAppId = this.getHandler(filePath, isDirectory);
            if (!handlerAppId) {
                return {
                    success: false,
                    error: `No handler found for ${isDirectory
                        ? "directories"
                        : `extension .${this.getExtension(filePath)}`}`,
                };
            }
            // Check if app is installed
            const manifest = this.packageManager.getAppManifest(handlerAppId);
            if (!manifest) {
                return {
                    success: false,
                    error: `Handler app ${handlerAppId} is not installed`,
                };
            }
            // Launch the app (or focus if already running)
            const instance = this.processManager.getAppInstance(handlerAppId);
            if (!instance) {
                // App not running - launch with file path as launch argument
                await this.processManager.launchApp(handlerAppId, undefined, [
                    filePath,
                ]);
            }
            else {
                // App already running - notify via event (app is already subscribed)
                const viewIds = this.viewManager.getViewsByAppId(handlerAppId);
                for (const viewId of viewIds) {
                    this.notifySubscriber(viewId, "opened", {
                        path: filePath,
                        isDirectory,
                        appId: handlerAppId,
                    });
                }
            }
            return {
                success: true,
                appId: handlerAppId,
            };
        }
        catch (error) {
            return {
                success: false,
                error: error instanceof Error ? error.message : String(error),
            };
        }
    }
    /**
     * Open a file with a specific app
     */
    async openFileWith(filePath, appId) {
        try {
            // Resolve masked path to full filesystem path
            const fullPath = this.fsManager.resolvePath(filePath);
            // Check if file exists and get stats
            const stats = await fs.stat(fullPath);
            const isDirectory = stats.isDirectory();
            // Check if app is installed
            const manifest = this.packageManager.getAppManifest(appId);
            if (!manifest) {
                return {
                    success: false,
                    error: `App ${appId} is not installed`,
                };
            }
            // Launch the app (or focus if already running)
            const instance = this.processManager.getAppInstance(appId);
            if (!instance) {
                // App not running - launch with file path as launch argument
                await this.processManager.launchApp(appId, undefined, [filePath]);
            }
            else {
                // App already running - notify via event (app is already subscribed)
                const viewIds = this.viewManager.getViewsByAppId(appId);
                for (const viewId of viewIds) {
                    this.notifySubscriber(viewId, "opened", {
                        path: filePath,
                        isDirectory,
                        appId,
                    });
                }
            }
            return {
                success: true,
                appId,
            };
        }
        catch (error) {
            return {
                success: false,
                error: error instanceof Error ? error.message : String(error),
            };
        }
    }
};
exports.FileOpenManager = FileOpenManager;
exports.FileOpenManager = FileOpenManager = FileOpenManager_1 = __decorate([
    (0, tsyringe_1.singleton)(),
    (0, tsyringe_1.injectable)(),
    (0, ipc_1.EdenNamespace)("file"),
    __param(0, (0, tsyringe_1.inject)("userDirectory")),
    __param(1, (0, tsyringe_1.inject)(package_manager_1.PackageManager)),
    __param(2, (0, tsyringe_1.inject)(process_manager_1.ProcessManager)),
    __param(3, (0, tsyringe_1.inject)(view_manager_1.ViewManager)),
    __param(4, (0, tsyringe_1.inject)(filesystem_1.FilesystemManager)),
    __param(5, (0, tsyringe_1.inject)(ipc_1.IPCBridge)),
    __param(6, (0, tsyringe_1.inject)(ipc_1.CommandRegistry)),
    __metadata("design:paramtypes", [String, package_manager_1.PackageManager,
        process_manager_1.ProcessManager,
        view_manager_1.ViewManager,
        filesystem_1.FilesystemManager,
        ipc_1.IPCBridge,
        ipc_1.CommandRegistry])
], FileOpenManager);
//# sourceMappingURL=FileOpenManager.js.map