"use strict";
/* eslint-disable @typescript-eslint/no-explicit-any */
/**
 * WASM Plugin Virtual Filesystem (VFS) Management
 *
 * Handles isolated storage for WASM plugins using WASI virtual filesystem.
 * Each plugin gets its own VFS root for secure, sandboxed file access.
 */
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 __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.getPluginStoragePaths = getPluginStoragePaths;
exports.initializePluginVfs = initializePluginVfs;
exports.readPluginConfig = readPluginConfig;
exports.writePluginConfig = writePluginConfig;
exports.migrateFromNodeJs = migrateFromNodeJs;
exports.cleanupVfsTmp = cleanupVfsTmp;
exports.getVfsDiskUsage = getVfsDiskUsage;
exports.deletePluginVfs = deletePluginVfs;
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const debug_1 = __importDefault(require("debug"));
const pluginid_1 = require("../pluginid");
const atomicWrite_1 = require("../atomicWrite");
const debug = (0, debug_1.default)('signalk:wasm:storage');
/**
 * Get storage paths for a WASM plugin
 *
 * @param configPath - Server config directory path
 * @param pluginId - Plugin ID (e.g., "hello-assemblyscript") - used for config file to match regular plugins
 * @param packageName - NPM package name (e.g., "@signalk/hello-assemblyscript") - used for VFS directory
 */
function getPluginStoragePaths(configPath, pluginId, packageName) {
    // Config file goes directly in plugin-config-data/ like regular plugins
    const configDataPath = path.join(configPath, 'plugin-config-data');
    // Use plugin ID for config file (matches regular Node.js plugins)
    const configFile = path.join(configDataPath, `${pluginId}.json`);
    // Use sanitized package name for VFS directory (for isolation)
    // Use same pattern as plugin ID: @ → _, / → _
    // @signalk/hello-assemblyscript -> _signalk_hello-assemblyscript
    const sanitizedPackageName = (0, pluginid_1.derivePluginId)(packageName);
    const pluginDataRoot = path.join(configDataPath, sanitizedPackageName);
    const vfsRoot = path.join(pluginDataRoot, 'vfs');
    return {
        pluginDataRoot,
        configFile, // e.g., ~/.signalk/plugin-config-data/_signalk_example-hello-assemblyscript.json
        vfsRoot, // e.g., ~/.signalk/plugin-config-data/_signalk_example-hello-assemblyscript/vfs/
        vfsData: path.join(vfsRoot, 'data'),
        vfsConfig: path.join(vfsRoot, 'config'),
        vfsTmp: path.join(vfsRoot, 'tmp')
    };
}
/**
 * Initialize VFS structure for a WASM plugin
 */
function initializePluginVfs(paths) {
    debug(`Initializing VFS for plugin at ${paths.vfsRoot}`);
    try {
        // Create VFS root and subdirectories
        const dirsToCreate = [
            paths.pluginDataRoot,
            paths.vfsRoot,
            paths.vfsData,
            paths.vfsConfig,
            paths.vfsTmp
        ];
        for (const dir of dirsToCreate) {
            if (!fs.existsSync(dir)) {
                fs.mkdirSync(dir, { recursive: true });
                debug(`Created directory: ${dir}`);
            }
        }
        debug(`VFS initialized successfully at ${paths.vfsRoot}`);
    }
    catch (error) {
        const errorMsg = error instanceof Error ? error.message : String(error);
        debug(`Failed to initialize VFS: ${errorMsg}`);
        throw new Error(`Failed to initialize plugin VFS: ${errorMsg}`);
    }
}
/**
 * Read plugin configuration from server-managed config file
 */
function readPluginConfig(configFile) {
    try {
        if (!fs.existsSync(configFile)) {
            debug(`Config file not found: ${configFile}, returning default config`);
            // Note: Do NOT include configuration key - UI shows "Configure" button when configuration is null/undefined
            return {
                enabled: false
            };
        }
        const configData = fs.readFileSync(configFile, 'utf8');
        return JSON.parse(configData);
    }
    catch (error) {
        const errorMsg = error instanceof Error ? error.message : String(error);
        debug(`Error reading plugin config: ${errorMsg}`);
        // Note: Do NOT include configuration key - UI shows "Configure" button when configuration is null/undefined
        return {
            enabled: false
        };
    }
}
/**
 * Write plugin configuration to server-managed config file
 */
function writePluginConfig(configFile, config) {
    try {
        const configDir = path.dirname(configFile);
        if (!fs.existsSync(configDir)) {
            fs.mkdirSync(configDir, { recursive: true });
        }
        (0, atomicWrite_1.atomicWriteFileSync)(configFile, JSON.stringify(config, null, 2));
        debug(`Wrote plugin config to ${configFile}`);
    }
    catch (error) {
        const errorMsg = error instanceof Error ? error.message : String(error);
        debug(`Error writing plugin config: ${errorMsg}`);
        throw new Error(`Failed to write plugin config: ${errorMsg}`);
    }
}
/**
 * Migrate data from Node.js plugin format to WASM VFS format
 *
 * Copies files from legacy Node.js plugin data directory to VFS /data directory.
 * Legacy files are preserved for rollback.
 */
function migrateFromNodeJs(legacyDataDir, vfsDataDir, filesToMigrate) {
    debug(`Migrating data from ${legacyDataDir} to ${vfsDataDir}`);
    if (!fs.existsSync(legacyDataDir)) {
        debug('Legacy data directory does not exist, skipping migration');
        return;
    }
    if (!fs.existsSync(vfsDataDir)) {
        fs.mkdirSync(vfsDataDir, { recursive: true });
    }
    let migratedCount = 0;
    for (const filename of filesToMigrate) {
        const legacyPath = path.join(legacyDataDir, filename);
        const vfsPath = path.join(vfsDataDir, filename);
        if (fs.existsSync(legacyPath)) {
            try {
                // Copy file to VFS (preserve legacy file)
                fs.copyFileSync(legacyPath, vfsPath);
                debug(`Migrated: ${filename}`);
                migratedCount++;
            }
            catch (error) {
                const errorMsg = error instanceof Error ? error.message : String(error);
                debug(`Failed to migrate ${filename}: ${errorMsg}`);
            }
        }
    }
    debug(`Migration complete: ${migratedCount}/${filesToMigrate.length} files migrated`);
}
/**
 * Clean up VFS temporary files
 */
function cleanupVfsTmp(vfsTmpDir) {
    try {
        if (!fs.existsSync(vfsTmpDir)) {
            return;
        }
        const files = fs.readdirSync(vfsTmpDir);
        let deletedCount = 0;
        for (const file of files) {
            try {
                const filePath = path.join(vfsTmpDir, file);
                const stats = fs.statSync(filePath);
                if (stats.isFile()) {
                    fs.unlinkSync(filePath);
                    deletedCount++;
                }
            }
            catch (error) {
                debug(`Failed to delete temp file ${file}:`, error);
            }
        }
        debug(`Cleaned up ${deletedCount} temporary files from ${vfsTmpDir}`);
    }
    catch (error) {
        debug(`Error cleaning up temp directory:`, error);
    }
}
/**
 * Get disk usage for a plugin's VFS
 */
function getVfsDiskUsage(vfsRoot) {
    let totalBytes = 0;
    let fileCount = 0;
    function walkDirectory(dir) {
        try {
            if (!fs.existsSync(dir)) {
                return;
            }
            const entries = fs.readdirSync(dir);
            for (const entry of entries) {
                const entryPath = path.join(dir, entry);
                const stats = fs.statSync(entryPath);
                if (stats.isFile()) {
                    totalBytes += stats.size;
                    fileCount++;
                }
                else if (stats.isDirectory()) {
                    walkDirectory(entryPath);
                }
            }
        }
        catch (error) {
            debug(`Error reading directory ${dir}:`, error);
        }
    }
    walkDirectory(vfsRoot);
    return { totalBytes, fileCount };
}
/**
 * Delete all VFS data for a plugin
 */
function deletePluginVfs(paths) {
    debug(`Deleting VFS for plugin at ${paths.vfsRoot}`);
    try {
        if (fs.existsSync(paths.vfsRoot)) {
            fs.rmSync(paths.vfsRoot, { recursive: true, force: true });
            debug(`Deleted VFS directory: ${paths.vfsRoot}`);
        }
        // Note: We keep the server-managed config file for plugin settings
        debug('VFS deletion complete');
    }
    catch (error) {
        const errorMsg = error instanceof Error ? error.message : String(error);
        debug(`Error deleting VFS: ${errorMsg}`);
        throw new Error(`Failed to delete plugin VFS: ${errorMsg}`);
    }
}
//# sourceMappingURL=wasm-storage.js.map