"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.parseSurfaceTargets = parseSurfaceTargets;
exports.findAppCatalogueInfo = findAppCatalogueInfo;
exports.findAppDefinition = findAppDefinition;
const node_fs_1 = require("node:fs");
const node_path_1 = require("node:path");
const types_1 = require("@playdrop/types");
function parseSurfaceTargets(input) {
    const map = { desktop: false, mobileLandscape: false, mobilePortrait: false };
    if (Array.isArray(input)) {
        for (const entry of input) {
            if (entry === 'DESKTOP')
                map.desktop = true;
            if (entry === 'MOBILE_LANDSCAPE')
                map.mobileLandscape = true;
            if (entry === 'MOBILE_PORTRAIT')
                map.mobilePortrait = true;
        }
    }
    else if (input && typeof input === 'object') {
        const source = input;
        for (const key of ['desktop', 'mobileLandscape', 'mobilePortrait']) {
            if (typeof source[key] !== 'boolean')
                throw new Error(`surfaceTargets.${key} must be a boolean.`);
            map[key] = Boolean(source[key]);
        }
    }
    else {
        throw new Error('surfaceTargets must be an object with desktop, mobileLandscape, and mobilePortrait booleans.');
    }
    if (!map.desktop && !map.mobileLandscape && !map.mobilePortrait) {
        throw new Error('surfaceTargets must enable at least one platform.');
    }
    const list = [];
    if (map.desktop)
        list.push('DESKTOP');
    if (map.mobileLandscape)
        list.push('MOBILE_LANDSCAPE');
    if (map.mobilePortrait)
        list.push('MOBILE_PORTRAIT');
    return { map, list };
}
const DEFAULT_SURFACE_TARGETS_OBJECT = { desktop: true, mobileLandscape: false, mobilePortrait: false };
const LEGACY_CATALOGUE_VERSION_KEY = ['schema', 'Version'].join('');
function parseCatalogueEntries(cataloguePath) {
    try {
        const raw = (0, node_fs_1.readFileSync)(cataloguePath, 'utf8');
        const data = JSON.parse(raw);
        if (!data || typeof data !== 'object' || Array.isArray(data)) {
            throw new Error('catalogue.json must be an object');
        }
        if (Object.prototype.hasOwnProperty.call(data, LEGACY_CATALOGUE_VERSION_KEY)) {
            throw new Error('legacy top-level version field is not supported');
        }
        const entries = data?.apps;
        return Array.isArray(entries)
            ? entries.filter((entry) => Boolean(entry && typeof entry === 'object'))
            : [];
    }
    catch {
        throw new Error(`Failed to parse ${cataloguePath}. Fix the JSON and retry.`);
    }
}
function findMatchingCatalogueEntries(apps, relativePath, fileName) {
    return apps.filter((entry) => {
        const entryName = typeof entry.name === 'string' ? entry.name.trim() : '';
        const entryFile = typeof entry.file === 'string' ? entry.file.trim() : `${entryName}.html`;
        const normalized = entryFile.replace(/\\/g, '/');
        return normalized === relativePath || normalized === fileName;
    });
}
function cloneSurfaceTargets(targets) {
    return {
        list: [...targets.list],
        map: { ...targets.map },
    };
}
function findAppCatalogueInfo(htmlPath) {
    const absolute = (0, node_path_1.resolve)(htmlPath);
    const fileName = (0, node_path_1.basename)(absolute);
    for (let dir = (0, node_path_1.dirname)(absolute);; dir = (0, node_path_1.dirname)(dir)) {
        const cataloguePath = (0, node_path_1.join)(dir, 'catalogue.json');
        if ((0, node_fs_1.existsSync)(cataloguePath) && (0, node_fs_1.statSync)(cataloguePath).isFile()) {
            const rel = (0, node_path_1.relative)(dir, absolute).replace(/\\/g, '/');
            const apps = parseCatalogueEntries(cataloguePath);
            const matches = findMatchingCatalogueEntries(apps, rel, fileName);
            if (matches.length > 1) {
                throw new Error(`Multiple entries in ${cataloguePath} reference ${absolute}.`);
            }
            if (matches.length === 1) {
                const match = matches[0];
                const typeValue = typeof match.type === 'string' ? match.type.trim() : '';
                const parsedType = (0, types_1.parseAppType)(typeValue);
                if (!parsedType) {
                    throw new Error(`Entry in ${cataloguePath} must include a valid type (${types_1.APP_TYPE_VALUES.join(', ')}).`);
                }
                const name = typeof match.name === 'string' && match.name.trim().length > 0
                    ? match.name.trim()
                    : fileName.replace(/\.html$/i, '');
                const ecsPath = typeof match.ecs === 'string' && match.ecs.trim().length > 0
                    ? (0, node_path_1.join)(dir, match.ecs.trim())
                    : null;
                const serverScriptPath = typeof match.server === 'string' && match.server.trim().length > 0
                    ? (0, node_path_1.join)(dir, match.server.trim())
                    : null;
                let surfaceTargets;
                try {
                    surfaceTargets = parseSurfaceTargets(match.surfaceTargets);
                }
                catch {
                    surfaceTargets = parseSurfaceTargets({ ...DEFAULT_SURFACE_TARGETS_OBJECT });
                }
                return {
                    name,
                    type: parsedType,
                    surfaceTargets: cloneSurfaceTargets(surfaceTargets),
                    cataloguePath,
                    ecsPath,
                    serverScriptPath,
                };
            }
        }
        const parent = (0, node_path_1.dirname)(dir);
        if (parent === dir)
            break;
    }
    throw new Error(`No catalogue entry references ${absolute}.`);
}
function findAppDefinition(htmlPath) {
    const info = findAppCatalogueInfo(htmlPath);
    return { name: info.name, type: info.type };
}
