'use strict';

/**
 * @file SceneImporter.ts
 * @description Base infrastructure for importing scenes from external game engine formats
 * PRO-1.3: Scene Format Interoperability
 *
 * Supports importing from:
 * - Unity (.unity, .prefab)
 * - Godot (.tscn, .tres)
 * - Tiled (.tmx, .tsx)
 * - LDtk (.ldtk, .ldtkl)
 * - Aseprite (.aseprite, .ase)
 * - OGMO (.ogmo, .json)
 * - GameMaker (.yy)
 * - Spine (.json, .atlas)
 * - DragonBones (.json)
 */
const IMPORT_SOURCES = {
    unity: {
        type: 'unity',
        name: 'Unity',
        description: 'Unity scene and prefab files',
        extensions: ['.unity', '.prefab', '.asset', '.meta'],
        supportsAnimation: true,
        supportsLayers: true,
        supportsTilemap: true,
    },
    godot: {
        type: 'godot',
        name: 'Godot',
        description: 'Godot scene and resource files',
        extensions: ['.tscn', '.tres', '.godot'],
        supportsAnimation: true,
        supportsLayers: true,
        supportsTilemap: true,
    },
    tiled: {
        type: 'tiled',
        name: 'Tiled',
        description: 'Tiled Map Editor files',
        extensions: ['.tmx', '.tsx', '.tx', '.tj'],
        supportsAnimation: true,
        supportsLayers: true,
        supportsTilemap: true,
    },
    ldtk: {
        type: 'ldtk',
        name: 'LDtk',
        description: 'LDtk Level Designer Toolkit',
        extensions: ['.ldtk', '.ldtkl'],
        supportsAnimation: false,
        supportsLayers: true,
        supportsTilemap: true,
    },
    aseprite: {
        type: 'aseprite',
        name: 'Aseprite',
        description: 'Aseprite sprite editor files',
        extensions: ['.aseprite', '.ase'],
        supportsAnimation: true,
        supportsLayers: true,
        supportsTilemap: false,
    },
    ogmo: {
        type: 'ogmo',
        name: 'OGMO',
        description: 'OGMO Editor levels',
        extensions: ['.ogmo', '.json'],
        supportsAnimation: false,
        supportsLayers: true,
        supportsTilemap: true,
    },
    gamemaker: {
        type: 'gamemaker',
        name: 'GameMaker',
        description: 'GameMaker Studio room files',
        extensions: ['.yy', '.yyp'],
        supportsAnimation: true,
        supportsLayers: true,
        supportsTilemap: true,
    },
    rpgmaker: {
        type: 'rpgmaker',
        name: 'RPG Maker',
        description: 'RPG Maker MV/MZ map files',
        extensions: ['.json'],
        supportsAnimation: true,
        supportsLayers: true,
        supportsTilemap: true,
    },
    spine: {
        type: 'spine',
        name: 'Spine',
        description: 'Spine skeletal animation',
        extensions: ['.json', '.skel', '.atlas'],
        supportsAnimation: true,
        supportsLayers: false,
        supportsTilemap: false,
    },
    dragonbones: {
        type: 'dragonbones',
        name: 'DragonBones',
        description: 'DragonBones skeletal animation',
        extensions: ['.json', '.dbbin'],
        supportsAnimation: true,
        supportsLayers: false,
        supportsTilemap: false,
    },
    live2d: {
        type: 'live2d',
        name: 'Live2D',
        description: 'Live2D Cubism character animation',
        extensions: ['.model3.json', '.moc3', '.cdi3.json'],
        supportsAnimation: true,
        supportsLayers: false,
        supportsTilemap: false,
    },
    spriter: {
        type: 'spriter',
        name: 'Spriter',
        description: 'Spriter Pro animations',
        extensions: ['.scml', '.scon'],
        supportsAnimation: true,
        supportsLayers: false,
        supportsTilemap: false,
    },
};
// ============================================================
// Abstract Scene Importer
// ============================================================
class SceneImporter {
    constructor(sourceType) {
        this.errors = [];
        this.warnings = [];
        this.sourceType = sourceType;
        this.options = { sourcePath: '' };
    }
    /** Get importer source info */
    getSourceInfo() {
        return IMPORT_SOURCES[this.sourceType];
    }
    /** Check if this importer can handle the given file */
    canHandle(filePath) {
        const ext = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();
        return this.getSourceInfo().extensions.includes(ext);
    }
    // ----------------------------------------
    // Helper Methods
    // ----------------------------------------
    addError(code, message, file, line, fatal = false) {
        this.errors.push({ code, message, file, line, fatal });
    }
    addWarning(code, message, file, suggestion) {
        this.warnings.push({ code, message, file, suggestion });
    }
    clearMessages() {
        this.errors = [];
        this.warnings = [];
    }
    /** Convert parsed scene to Nice2Dev scene */
    convertToNiceScene(parsed) {
        const entities = this.flattenEntities(parsed.entities, parsed.layers);
        return {
            id: this.generateId(),
            name: parsed.name,
            entities: entities.map((e) => this.convertToNiceEntity(e)),
            settings: {
                width: parsed.width || 1920,
                height: parsed.height || 1080,
                backgroundColor: parsed.backgroundColor || '#1a1a2e',
                gravity: { x: 0, y: 980 },
                ...parsed.properties,
            },
        };
    }
    /** Alias for convertToNiceScene (used by subclass importers) */
    convertParsedToNiceScene(parsed) {
        return this.convertToNiceScene(parsed);
    }
    /** Flatten layer-based entities into single list */
    flattenEntities(entities, layers) {
        const result = [...entities];
        for (const layer of layers) {
            if (layer.objects) {
                for (const obj of layer.objects) {
                    result.push({
                        ...obj,
                        properties: {
                            ...obj.properties,
                            layerName: layer.name,
                            zIndex: layer.zIndex,
                        },
                    });
                }
            }
        }
        return result;
    }
    /** Convert parsed entity to Nice2Dev entity */
    convertToNiceEntity(parsed) {
        const components = [];
        // Transform component
        components.push({
            type: 'Transform',
            data: {
                position: { x: parsed.x, y: parsed.y },
                rotation: parsed.rotation,
                scale: { x: parsed.scaleX, y: parsed.scaleY },
            },
        });
        // Convert parsed components
        for (const comp of parsed.components) {
            components.push(this.convertComponent(comp));
        }
        return {
            id: parsed.id || this.generateId(),
            name: parsed.name,
            components,
            children: parsed.children.map((c) => this.convertToNiceEntity(c)),
            tags: parsed.type ? [parsed.type] : [],
            active: parsed.visible,
        };
    }
    /** Convert a component from source format to Nice2Dev format */
    convertComponent(parsed) {
        // This should be overridden by specific importers
        return {
            type: parsed.type,
            data: parsed.data,
        };
    }
    /** Convert parsed asset to Nice2Dev asset */
    convertToNiceAsset(parsed) {
        return {
            id: parsed.id || this.generateId(),
            name: parsed.name,
            type: parsed.type,
            path: parsed.path,
            data: parsed.metadata,
        };
    }
    /** Generate unique ID */
    generateId() {
        return `nice_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`;
    }
    /** Create empty import result */
    createEmptyResult() {
        return {
            success: false,
            scenes: [],
            entities: [],
            assets: [],
            errors: [],
            warnings: [],
            statistics: {
                scenesImported: 0,
                entitiesImported: 0,
                assetsImported: 0,
                animationsImported: 0,
                tilemapsImported: 0,
                scriptsConverted: 0,
                importDurationMs: 0,
            },
        };
    }
    /** Create successful result */
    createResult(scenes, assets, startTime, project) {
        const entities = scenes.flatMap((s) => s.entities);
        return {
            success: this.errors.filter((e) => e.fatal).length === 0,
            project,
            scenes,
            entities,
            assets,
            errors: [...this.errors],
            warnings: [...this.warnings],
            statistics: {
                scenesImported: scenes.length,
                entitiesImported: entities.length,
                assetsImported: assets.length,
                animationsImported: assets.filter((a) => a.type === 'animation').length,
                tilemapsImported: scenes.filter((s) => s.entities.some((e) => e.components.some((c) => c.type === 'Tilemap'))).length,
                scriptsConverted: assets.filter((a) => a.type === 'script').length,
                importDurationMs: Date.now() - startTime,
            },
        };
    }
}
// ============================================================
// Utility Functions
// ============================================================
/** Parse YAML content (basic implementation) */
function parseYAML(content) {
    // Basic YAML parser for Unity files
    const lines = content.split('\n');
    const result = {};
    const stack = [{ obj: result, indent: -1 }];
    for (const line of lines) {
        if (line.trim() === '' || line.trim().startsWith('#') || line.trim().startsWith('%')) {
            continue;
        }
        const indent = line.search(/\S/);
        const trimmed = line.trim();
        // Pop stack until we find parent
        while (stack.length > 1 && stack[stack.length - 1].indent >= indent) {
            stack.pop();
        }
        const parent = stack[stack.length - 1].obj;
        if (trimmed.startsWith('- ')) {
            // Array item
            const key = Object.keys(parent).pop();
            if (key && !Array.isArray(parent[key])) {
                parent[key] = [];
            }
            if (key && Array.isArray(parent[key])) {
                const value = trimmed.substring(2);
                if (value.includes(':')) {
                    const obj = {};
                    const [k, v] = value.split(':').map((s) => s.trim());
                    obj[k] = parseYAMLValue(v);
                    parent[key].push(obj);
                    stack.push({ obj, indent });
                }
                else {
                    parent[key].push(parseYAMLValue(value));
                }
            }
        }
        else if (trimmed.includes(':')) {
            const colonIndex = trimmed.indexOf(':');
            const key = trimmed.substring(0, colonIndex).trim();
            const value = trimmed.substring(colonIndex + 1).trim();
            if (value === '' || value === '|' || value === '>') {
                // Nested object or multiline string
                parent[key] = {};
                stack.push({ obj: parent[key], indent });
            }
            else if (value.startsWith('{') && value.endsWith('}')) {
                // Inline object
                parent[key] = parseInlineYAMLObject(value);
            }
            else {
                parent[key] = parseYAMLValue(value);
            }
        }
    }
    return result;
}
function parseYAMLValue(value) {
    if (value === 'true')
        return true;
    if (value === 'false')
        return false;
    if (value === 'null' || value === '~')
        return null;
    if (/^-?\d+$/.test(value))
        return parseInt(value, 10);
    if (/^-?\d+\.\d+$/.test(value))
        return parseFloat(value);
    if ((value.startsWith('"') && value.endsWith('"')) ||
        (value.startsWith("'") && value.endsWith("'"))) {
        return value.slice(1, -1);
    }
    return value;
}
function parseInlineYAMLObject(value) {
    const result = {};
    const content = value.slice(1, -1).trim();
    const pairs = content.split(',').map((s) => s.trim());
    for (const pair of pairs) {
        const [k, v] = pair.split(':').map((s) => s.trim());
        result[k] = parseYAMLValue(v);
    }
    return result;
}
/** Parse XML content to object */
function parseXML(content) {
    const parser = new DOMParser();
    const doc = parser.parseFromString(content, 'text/xml');
    return xmlToObject(doc.documentElement);
}
function xmlToObject(element) {
    var _a;
    const result = {
        name: element.tagName,
        attributes: {},
        children: [],
        text: '',
    };
    // Get attributes
    for (const attr of Array.from(element.attributes)) {
        result.attributes[attr.name] = attr.value;
    }
    // Get children
    for (const child of Array.from(element.children)) {
        result.children.push(xmlToObject(child));
    }
    // Get text content
    const textNode = Array.from(element.childNodes).find((n) => n.nodeType === Node.TEXT_NODE);
    if (textNode) {
        result.text = ((_a = textNode.textContent) === null || _a === void 0 ? void 0 : _a.trim()) || '';
    }
    return result;
}
/** Detect import source type from file */
function detectSourceType(filePath, content) {
    const ext = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();
    // By extension
    for (const [type, info] of Object.entries(IMPORT_SOURCES)) {
        if (info.extensions.includes(ext)) {
            // Handle ambiguous extensions
            if (ext === '.json' && content) {
                // Check content to distinguish between formats
                if (content.includes('"ldtkVersion"'))
                    return 'ldtk';
                if (content.includes('"ogmoVersion"'))
                    return 'ogmo';
                if (content.includes('"skeleton"') && content.includes('"bones"'))
                    return 'spine';
                if (content.includes('"armature"') && content.includes('"slot"'))
                    return 'dragonbones';
                if (content.includes('"FileVersion"') && content.includes('"Cubism"'))
                    return 'live2d';
                if (content.includes('"events"') && content.includes('"tilesets"'))
                    return 'rpgmaker';
            }
            return type;
        }
    }
    return null;
}
/** Get all available importers */
function getAvailableImporters() {
    return Object.values(IMPORT_SOURCES);
}
/** Check if an importer exists for the given source type */
function hasImporter(sourceType) {
    return sourceType in IMPORT_SOURCES;
}

exports.IMPORT_SOURCES = IMPORT_SOURCES;
exports.SceneImporter = SceneImporter;
exports.detectSourceType = detectSourceType;
exports.getAvailableImporters = getAvailableImporters;
exports.hasImporter = hasImporter;
exports.parseXML = parseXML;
exports.parseYAML = parseYAML;
//# sourceMappingURL=SceneImporter.js.map
