'use strict';

var SceneImporter = require('./SceneImporter.js');

/**
 * @file RPGMakerImporter.ts
 * @description RPG Maker Map Importer
 * PRO-1.3: Scene Format Interoperability
 *
 * Supports RPG Maker MV/MZ JSON map format.
 *
 * File Types:
 * - Map*.json - Map files
 * - Tilesets.json - Tileset definitions
 * - Actors.json, Enemies.json, etc. - Database files
 */
// ============================================================
// RPG Maker Tile Constants
// ============================================================
const TILE_SIZE = 48;
// Event trigger types
const TRIGGER_ACTION_BUTTON = 0;
const TRIGGER_PLAYER_TOUCH = 1;
const TRIGGER_EVENT_TOUCH = 2;
const TRIGGER_AUTORUN = 3;
const TRIGGER_PARALLEL = 4;
// Event priority types
const PRIORITY_BELOW = 0;
const PRIORITY_SAME = 1;
const PRIORITY_ABOVE = 2;
// ============================================================
// RPG Maker Importer
// ============================================================
class RPGMakerImporter extends SceneImporter.SceneImporter {
    constructor() {
        super('rpgmaker');
        this.tilesets = new Map();
        this.commonEvents = new Map();
    }
    canHandle(filePath) {
        const name = filePath.toLowerCase();
        return (name.endsWith('.json') &&
            (name.includes('map') ||
                name.includes('tilesets') ||
                name.includes('actors') ||
                name.includes('commonevents')));
    }
    async import(options) {
        const startTime = Date.now();
        this.options = options;
        this.clearMessages();
        const scenes = [];
        const assets = [];
        try {
            const content = await this.readFile(options.sourcePath);
            const data = JSON.parse(content);
            const fileName = options.sourcePath.toLowerCase();
            // Load tilesets if available
            if (options.resolveDependencies) {
                try {
                    const tilesetsPath = this.getDataPath(options.sourcePath, 'Tilesets.json');
                    const tilesetsContent = await this.readFile(tilesetsPath);
                    const tilesetsData = JSON.parse(tilesetsContent);
                    for (const tileset of tilesetsData) {
                        if (tileset) {
                            this.tilesets.set(tileset.id, tileset);
                        }
                    }
                }
                catch (_a) {
                    this.addWarning('TILESETS_NOT_FOUND', 'Tilesets.json not found', options.sourcePath);
                }
            }
            // Determine file type and process
            if (this.isMapFile(fileName, data)) {
                const map = data;
                const scene = this.convertMapToScene(map, options.sourcePath);
                scenes.push(scene);
                // Extract tileset assets
                const tileset = this.tilesets.get(map.tilesetId);
                if (tileset) {
                    for (const tilesetName of tileset.tilesetNames) {
                        if (tilesetName) {
                            assets.push({
                                id: this.generateId(),
                                name: tilesetName,
                                type: 'tileset',
                                path: `img/tilesets/${tilesetName}.png`,
                                data: { rpgMaker: true },
                            });
                        }
                    }
                }
                // Extract character assets from events
                for (const event of map.events) {
                    if (event) {
                        for (const page of event.pages) {
                            if (page.image.characterName) {
                                assets.push({
                                    id: this.generateId(),
                                    name: page.image.characterName,
                                    type: 'texture',
                                    path: `img/characters/${page.image.characterName}.png`,
                                    data: { characterIndex: page.image.characterIndex },
                                });
                            }
                        }
                    }
                }
            }
            else if (fileName.includes('tilesets')) {
                // Process tilesets database
                const tilesetsData = data;
                for (const tileset of tilesetsData) {
                    if (tileset) {
                        for (const tilesetName of tileset.tilesetNames) {
                            if (tilesetName) {
                                assets.push({
                                    id: this.generateId(),
                                    name: tilesetName,
                                    type: 'tileset',
                                    path: `img/tilesets/${tilesetName}.png`,
                                    data: {
                                        rpgMakerId: tileset.id,
                                        mode: tileset.mode,
                                    },
                                });
                            }
                        }
                    }
                }
            }
        }
        catch (error) {
            this.addError('IMPORT_ERROR', `Failed to import: ${error}`, options.sourcePath, undefined, true);
        }
        return this.createResult(scenes, assets, startTime);
    }
    async parseFile(content, filePath) {
        const stringContent = typeof content === 'string' ? content : new TextDecoder().decode(content);
        try {
            const data = JSON.parse(stringContent);
            const fileName = filePath.toLowerCase();
            if (this.isMapFile(fileName, data)) {
                return this.convertMapToParsed(data);
            }
        }
        catch (_a) {
            return null;
        }
        return null;
    }
    async validate(sourcePath) {
        const errors = [];
        if (!this.canHandle(sourcePath)) {
            errors.push({
                code: 'INVALID_FORMAT',
                message: `File ${sourcePath} is not a valid RPG Maker file`,
                file: sourcePath,
                fatal: true,
            });
        }
        return errors;
    }
    // ----------------------------------------
    // Type Checks
    // ----------------------------------------
    isMapFile(fileName, data) {
        const obj = data;
        return ((fileName.includes('map') || fileName.match(/map\d+\.json$/i) !== null) &&
            typeof obj === 'object' &&
            obj !== null &&
            'width' in obj &&
            'height' in obj &&
            'data' in obj &&
            'events' in obj);
    }
    // ----------------------------------------
    // Map Conversion
    // ----------------------------------------
    convertMapToScene(map, sourcePath) {
        const name = map.displayName || this.extractFileName(sourcePath);
        const entities = [];
        // Create tilemap layers (RPG Maker has 6 layers in data array)
        const layers = this.createTilemapLayers(map);
        entities.push(...layers);
        // Convert events
        for (const event of map.events) {
            if (event) {
                entities.push(this.convertEvent(event, map));
            }
        }
        // Create parallax if present
        if (map.parallaxName) {
            entities.push(this.createParallaxEntity(map));
        }
        return {
            id: this.generateId(),
            name,
            entities,
            settings: {
                width: map.width * TILE_SIZE,
                height: map.height * TILE_SIZE,
                backgroundColor: '#000000',
                tilesetId: map.tilesetId,
                encounterStep: map.encounterStep,
                scrollType: map.scrollType,
                autoplayBgm: map.autoplayBgm,
                autoplayBgs: map.autoplayBgs,
                bgm: map.bgm,
                bgs: map.bgs,
                note: map.note,
            },
        };
    }
    convertMapToParsed(map) {
        const layers = [];
        const entities = [];
        // Create tile layers
        const layerNames = ['Ground', 'Ground2', 'Upper', 'Upper2', 'Shadow', 'Region'];
        for (let z = 0; z < 6; z++) {
            const layerData = this.extractLayerData(map.data, z, map.width, map.height);
            layers.push({
                name: layerNames[z],
                type: z === 4 ? 'object' : 'tile', // Shadow layer is special
                visible: z !== 5, // Region layer is hidden
                opacity: 1,
                offsetX: 0,
                offsetY: 0,
                zIndex: z,
                tileData: {
                    width: map.width,
                    height: map.height,
                    tiles: layerData,
                    tileWidth: TILE_SIZE,
                    tileHeight: TILE_SIZE,
                },
                properties: {},
            });
        }
        // Convert events
        for (const event of map.events) {
            if (event) {
                entities.push(this.convertEventToParsed(event));
            }
        }
        return {
            name: map.displayName || 'RPG Maker Map',
            width: map.width * TILE_SIZE,
            height: map.height * TILE_SIZE,
            backgroundColor: '#000000',
            layers,
            entities,
            properties: {
                tilesetId: map.tilesetId,
                note: map.note,
            },
        };
    }
    // ----------------------------------------
    // Tilemap Layers
    // ----------------------------------------
    createTilemapLayers(map) {
        const entities = [];
        const layerNames = ['Ground', 'Ground2', 'Upper', 'Upper2', 'Shadow', 'Region'];
        for (let z = 0; z < 6; z++) {
            const layerData = this.extractLayerData(map.data, z, map.width, map.height);
            entities.push({
                id: this.generateId(),
                name: layerNames[z],
                components: [
                    {
                        type: 'Transform',
                        data: {
                            position: { x: 0, y: 0 },
                            rotation: 0,
                            scale: { x: 1, y: 1 },
                        },
                    },
                    {
                        type: 'Tilemap',
                        data: {
                            width: map.width,
                            height: map.height,
                            tileWidth: TILE_SIZE,
                            tileHeight: TILE_SIZE,
                            data: layerData,
                            tilesetId: map.tilesetId,
                            layerIndex: z,
                            visible: z !== 5, // Hide region layer
                        },
                    },
                ],
                children: [],
                tags: ['tilemap', layerNames[z].toLowerCase()],
                active: true,
            });
        }
        return entities;
    }
    extractLayerData(data, layer, width, height) {
        const layerData = [];
        const layerSize = width * height;
        const startIndex = layer * layerSize;
        for (let i = 0; i < layerSize; i++) {
            layerData.push(data[startIndex + i]);
        }
        return layerData;
    }
    // ----------------------------------------
    // Event Conversion
    // ----------------------------------------
    convertEvent(event, map) {
        const activePage = this.getActivePage(event);
        const components = [
            {
                type: 'Transform',
                data: {
                    position: {
                        x: event.x * TILE_SIZE + TILE_SIZE / 2,
                        y: event.y * TILE_SIZE + TILE_SIZE / 2,
                    },
                    rotation: 0,
                    scale: { x: 1, y: 1 },
                },
            },
        ];
        // Add sprite if event has image
        if (activePage && activePage.image.characterName) {
            components.push({
                type: 'Sprite',
                data: {
                    texture: activePage.image.characterName,
                    characterIndex: activePage.image.characterIndex,
                    direction: activePage.image.direction,
                    pattern: activePage.image.pattern,
                    animation: activePage.walkAnime || activePage.stepAnime,
                },
            });
        }
        else if (activePage && activePage.image.tileId > 0) {
            components.push({
                type: 'Sprite',
                data: {
                    tileId: activePage.image.tileId,
                    tilesetId: map.tilesetId,
                },
            });
        }
        // Add event trigger component
        if (activePage) {
            components.push({
                type: 'EventTrigger',
                data: {
                    trigger: this.getTriggerName(activePage.trigger),
                    priority: this.getPriorityName(activePage.priorityType),
                    moveType: activePage.moveType,
                    moveSpeed: activePage.moveSpeed,
                    moveFrequency: activePage.moveFrequency,
                    directionFix: activePage.directionFix,
                    through: activePage.through,
                },
            });
            // Add event commands as script
            if (activePage.list.length > 0) {
                components.push({
                    type: 'EventScript',
                    data: {
                        commands: this.simplifyCommands(activePage.list),
                        conditions: activePage.conditions,
                    },
                });
            }
        }
        return {
            id: event.id.toString(),
            name: event.name,
            components,
            children: [],
            tags: ['event'],
            active: true,
        };
    }
    convertEventToParsed(event) {
        const activePage = this.getActivePage(event);
        return {
            id: event.id.toString(),
            name: event.name,
            type: 'Event',
            x: event.x * TILE_SIZE + TILE_SIZE / 2,
            y: event.y * TILE_SIZE + TILE_SIZE / 2,
            width: TILE_SIZE,
            height: TILE_SIZE,
            rotation: 0,
            scaleX: 1,
            scaleY: 1,
            visible: true,
            components: [],
            children: [],
            properties: {
                note: event.note,
                pages: event.pages.length,
                trigger: activePage ? this.getTriggerName(activePage.trigger) : 'none',
                characterName: activePage === null || activePage === void 0 ? void 0 : activePage.image.characterName,
                characterIndex: activePage === null || activePage === void 0 ? void 0 : activePage.image.characterIndex,
            },
        };
    }
    getActivePage(event) {
        // In editor context, return first page
        // In runtime, would evaluate conditions
        return event.pages.length > 0 ? event.pages[0] : null;
    }
    getTriggerName(trigger) {
        switch (trigger) {
            case TRIGGER_ACTION_BUTTON:
                return 'action';
            case TRIGGER_PLAYER_TOUCH:
                return 'playerTouch';
            case TRIGGER_EVENT_TOUCH:
                return 'eventTouch';
            case TRIGGER_AUTORUN:
                return 'autorun';
            case TRIGGER_PARALLEL:
                return 'parallel';
            default:
                return 'action';
        }
    }
    getPriorityName(priority) {
        switch (priority) {
            case PRIORITY_BELOW:
                return 'below';
            case PRIORITY_SAME:
                return 'same';
            case PRIORITY_ABOVE:
                return 'above';
            default:
                return 'same';
        }
    }
    simplifyCommands(commands) {
        return commands.map((cmd) => ({
            code: cmd.code,
            indent: cmd.indent,
            params: cmd.parameters,
        }));
    }
    // ----------------------------------------
    // Parallax
    // ----------------------------------------
    createParallaxEntity(map) {
        return {
            id: this.generateId(),
            name: 'Parallax',
            components: [
                {
                    type: 'Transform',
                    data: {
                        position: { x: 0, y: 0 },
                        rotation: 0,
                        scale: { x: 1, y: 1 },
                    },
                },
                {
                    type: 'Parallax',
                    data: {
                        texture: map.parallaxName,
                        loopX: map.parallaxLoopX,
                        loopY: map.parallaxLoopY,
                        scrollX: map.parallaxSx,
                        scrollY: map.parallaxSy,
                        visible: map.parallaxShow,
                    },
                },
            ],
            children: [],
            tags: ['parallax'],
            active: true,
        };
    }
    // ----------------------------------------
    // Utilities
    // ----------------------------------------
    async readFile(path) {
        var _a;
        if (typeof globalThis.process !== 'undefined' && ((_a = globalThis.process.versions) === null || _a === void 0 ? void 0 : _a.node)) {
            const fs = await import('fs');
            return fs.readFileSync(path, 'utf-8');
        }
        else if (typeof fetch !== 'undefined') {
            const response = await fetch(path);
            return response.text();
        }
        throw new Error('Unable to read file in current environment');
    }
    getDataPath(sourcePath, fileName) {
        const dir = sourcePath.substring(0, sourcePath.lastIndexOf('/') + 1);
        // Navigate to data folder
        if (dir.includes('/data/')) {
            return dir + fileName;
        }
        return dir + 'data/' + fileName;
    }
    extractFileName(path) {
        const name = path.substring(path.lastIndexOf('/') + 1);
        const dotIndex = name.lastIndexOf('.');
        return dotIndex > 0 ? name.substring(0, dotIndex) : name;
    }
}
// ============================================================
// Factory Function
// ============================================================
function createRPGMakerImporter() {
    return new RPGMakerImporter();
}

exports.RPGMakerImporter = RPGMakerImporter;
exports.createRPGMakerImporter = createRPGMakerImporter;
//# sourceMappingURL=RPGMakerImporter.js.map
