import { SceneImporter } from './SceneImporter.js';

/**
 * @file NdgFormat.ts
 * @description Nice2Dev Game (.ndg) Universal Format - Import/Export
 * PRO-1.3: Scene Format Interoperability
 *
 * The .ndg format is Nice2Dev's native scene interchange format.
 * Designed for:
 * - Lossless round-trip conversion
 * - Human-readable JSON structure
 * - Full feature preservation
 * - Version compatibility
 *
 * File Types:
 * - .ndg - Single scene
 * - .ndgp - Project with multiple scenes
 * - .ndga - Asset bundle
 */
// ============================================================
// NDG Format Version
// ============================================================
const NDG_FORMAT_VERSION = '1.0.0';
const NDG_MAGIC = 'NDG1';
// ============================================================
// NDG Importer
// ============================================================
class NdgImporter extends SceneImporter {
    constructor() {
        super('unity'); // Use unity as base, but this handles .ndg files
        this.ndgFile = null;
    }
    canHandle(filePath) {
        const ext = filePath.substring(filePath.lastIndexOf('.')).toLowerCase();
        return ['.ndg', '.ndgp', '.ndga'].includes(ext);
    }
    async import(options) {
        const startTime = Date.now();
        this.options = options;
        this.clearMessages();
        const scenes = [];
        const assets = [];
        try {
            const content = await this.readFile(options.sourcePath);
            this.ndgFile = JSON.parse(content);
            // Validate format
            if (this.ndgFile.magic !== NDG_MAGIC) {
                this.addError('INVALID_MAGIC', 'Invalid NDG file magic', options.sourcePath, undefined, true);
                return { ...this.createEmptyResult(), errors: this.errors };
            }
            // Convert based on file type
            if (this.ndgFile.type === 'scene') {
                const scene = this.convertNdgSceneToNice(this.ndgFile.content);
                scenes.push(scene);
            }
            else if (this.ndgFile.type === 'project') {
                const project = this.ndgFile.content;
                for (const ndgScene of project.scenes) {
                    scenes.push(this.convertNdgSceneToNice(ndgScene));
                }
                for (const ndgAsset of project.assets) {
                    assets.push(this.convertNdgAssetToNice(ndgAsset));
                }
            }
            else if (this.ndgFile.type === 'asset-bundle') {
                const bundle = this.ndgFile.content;
                for (const ndgAsset of bundle.assets) {
                    assets.push(this.convertNdgAssetToNice(ndgAsset));
                }
            }
        }
        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 ndgFile = JSON.parse(stringContent);
            if (ndgFile.type === 'scene') {
                const scene = ndgFile.content;
                return this.convertNdgSceneToParsed(scene);
            }
        }
        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 NDG file`,
                file: sourcePath,
                fatal: true,
            });
        }
        return errors;
    }
    // ----------------------------------------
    // Conversion
    // ----------------------------------------
    convertNdgSceneToNice(ndgScene) {
        return {
            id: ndgScene.id,
            name: ndgScene.name,
            entities: ndgScene.entities.map((e) => this.convertNdgEntityToNice(e)),
            settings: {
                width: ndgScene.settings.width,
                height: ndgScene.settings.height,
                backgroundColor: ndgScene.settings.backgroundColor,
                gravity: ndgScene.settings.gravity,
                ...ndgScene.metadata,
            },
        };
    }
    convertNdgEntityToNice(ndgEntity) {
        return {
            id: ndgEntity.id,
            name: ndgEntity.name,
            components: [
                {
                    type: 'Transform',
                    data: {
                        position: ndgEntity.transform.position,
                        rotation: ndgEntity.transform.rotation,
                        scale: ndgEntity.transform.scale,
                    },
                },
                ...ndgEntity.components.map((c) => ({
                    type: c.type,
                    data: c.data,
                })),
            ],
            children: ndgEntity.children.map((c) => this.convertNdgEntityToNice(c)),
            tags: ndgEntity.tags,
            active: ndgEntity.active,
        };
    }
    convertNdgAssetToNice(ndgAsset) {
        return {
            id: ndgAsset.id,
            name: ndgAsset.name,
            type: ndgAsset.type,
            path: ndgAsset.path,
            data: ndgAsset.data || {},
        };
    }
    convertNdgSceneToParsed(ndgScene) {
        var _a;
        return {
            name: ndgScene.name,
            width: ndgScene.settings.width,
            height: ndgScene.settings.height,
            backgroundColor: ndgScene.settings.backgroundColor,
            layers: ((_a = ndgScene.layers) === null || _a === void 0 ? void 0 : _a.map((l, i) => ({
                name: l.name,
                type: 'object',
                visible: l.visible,
                opacity: 1,
                offsetX: 0,
                offsetY: 0,
                zIndex: l.zIndex,
                properties: l.properties || {},
            }))) || [],
            entities: ndgScene.entities.map((e) => this.convertNdgEntityToParsed(e)),
            properties: {
                ...ndgScene.settings,
                ...ndgScene.metadata,
            },
        };
    }
    convertNdgEntityToParsed(ndgEntity) {
        return {
            id: ndgEntity.id,
            name: ndgEntity.name,
            type: ndgEntity.tags[0] || 'Entity',
            x: ndgEntity.transform.position.x,
            y: ndgEntity.transform.position.y,
            width: 1,
            height: 1,
            rotation: typeof ndgEntity.transform.rotation === 'number'
                ? ndgEntity.transform.rotation
                : ndgEntity.transform.rotation.z,
            scaleX: ndgEntity.transform.scale.x,
            scaleY: ndgEntity.transform.scale.y,
            visible: ndgEntity.active,
            components: ndgEntity.components.map((c) => ({
                type: c.type,
                data: c.data,
            })),
            children: ndgEntity.children.map((c) => this.convertNdgEntityToParsed(c)),
            properties: {
                tags: ndgEntity.tags,
                layer: ndgEntity.layer,
                ...ndgEntity.metadata,
            },
        };
    }
    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');
    }
}
// ============================================================
// NDG Exporter
// ============================================================
class NdgExporter {
    constructor() {
        this.generatorName = 'Nice2Dev';
        this.generatorVersion = '1.0.0';
    }
    /**
     * Export a single scene to NDG format
     */
    exportScene(scene, source) {
        const now = new Date().toISOString();
        return {
            magic: NDG_MAGIC,
            version: NDG_FORMAT_VERSION,
            type: 'scene',
            created: now,
            modified: now,
            generator: {
                name: this.generatorName,
                version: this.generatorVersion,
            },
            source,
            content: this.convertNiceSceneToNdg(scene),
        };
    }
    /**
     * Export a full project to NDG format
     */
    exportProject(project) {
        const now = new Date().toISOString();
        return {
            magic: NDG_MAGIC,
            version: NDG_FORMAT_VERSION,
            type: 'project',
            created: now,
            modified: now,
            generator: {
                name: this.generatorName,
                version: this.generatorVersion,
            },
            content: this.convertNiceProjectToNdg(project),
        };
    }
    /**
     * Export an asset bundle to NDG format
     */
    exportAssetBundle(name, assets) {
        const now = new Date().toISOString();
        return {
            magic: NDG_MAGIC,
            version: NDG_FORMAT_VERSION,
            type: 'asset-bundle',
            created: now,
            modified: now,
            generator: {
                name: this.generatorName,
                version: this.generatorVersion,
            },
            content: {
                name,
                assets: assets.map((a) => this.convertNiceAssetToNdg(a)),
            },
        };
    }
    /**
     * Serialize NDG file to JSON string
     */
    serialize(ndgFile, pretty = true) {
        return JSON.stringify(ndgFile, null, pretty ? 2 : undefined);
    }
    // ----------------------------------------
    // Conversion
    // ----------------------------------------
    convertNiceSceneToNdg(scene) {
        const settings = scene.settings || {};
        return {
            id: scene.id,
            name: scene.name,
            settings: {
                width: settings.width || 1920,
                height: settings.height || 1080,
                backgroundColor: settings.backgroundColor || '#1a1a2e',
                gravity: settings.gravity,
            },
            entities: scene.entities.map((e) => this.convertNiceEntityToNdg(e)),
            metadata: this.extractMetadata(settings),
        };
    }
    convertNiceEntityToNdg(entity) {
        var _a;
        const transformComp = entity.components.find((c) => c.type === 'Transform');
        const transform = (transformComp === null || transformComp === void 0 ? void 0 : transformComp.data) || {};
        return {
            id: entity.id,
            name: entity.name,
            active: (_a = entity.active) !== null && _a !== void 0 ? _a : true,
            tags: entity.tags || [],
            transform: {
                position: transform.position || { x: 0, y: 0 },
                rotation: transform.rotation || 0,
                scale: transform.scale || { x: 1, y: 1 },
            },
            components: entity.components
                .filter((c) => c.type !== 'Transform')
                .map((c) => {
                var _a;
                return ({
                    type: c.type,
                    enabled: true,
                    data: (_a = c.data) !== null && _a !== void 0 ? _a : {},
                });
            }),
            children: (entity.children || []).map((c) => this.convertNiceEntityToNdg(c)),
        };
    }
    convertNiceProjectToNdg(project) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r;
        return {
            name: project.name,
            description: project.description,
            settings: {
                width: ((_a = project.settings) === null || _a === void 0 ? void 0 : _a.width) || 1920,
                height: ((_b = project.settings) === null || _b === void 0 ? void 0 : _b.height) || 1080,
                physics: ((_c = project.settings) === null || _c === void 0 ? void 0 : _c.physics)
                    ? {
                        gravity: project.settings.physics.gravity,
                        velocityIterations: (_d = project.settings.physics.velocityIterations) !== null && _d !== void 0 ? _d : 8,
                        positionIterations: (_e = project.settings.physics.positionIterations) !== null && _e !== void 0 ? _e : 3,
                        timeStep: (_f = project.settings.physics.timeStep) !== null && _f !== void 0 ? _f : 1 / 60,
                    }
                    : undefined,
                audio: ((_g = project.settings) === null || _g === void 0 ? void 0 : _g.audio)
                    ? {
                        masterVolume: project.settings.audio.masterVolume,
                        musicVolume: (_h = project.settings.audio.musicVolume) !== null && _h !== void 0 ? _h : 1,
                        sfxVolume: (_j = project.settings.audio.sfxVolume) !== null && _j !== void 0 ? _j : 1,
                        audioChannels: (_k = project.settings.audio.audioChannels) !== null && _k !== void 0 ? _k : 32,
                    }
                    : undefined,
                rendering: ((_l = project.settings) === null || _l === void 0 ? void 0 : _l.rendering)
                    ? {
                        pixelPerfect: (_m = project.settings.rendering.pixelPerfect) !== null && _m !== void 0 ? _m : project.settings.rendering.pixelArt,
                        antialiasing: (_o = project.settings.rendering.antialiasing) !== null && _o !== void 0 ? _o : project.settings.rendering.antialias,
                        vsync: (_p = project.settings.rendering.vsync) !== null && _p !== void 0 ? _p : true,
                        backgroundColor: (_q = project.settings.rendering.backgroundColor) !== null && _q !== void 0 ? _q : '#000000',
                    }
                    : undefined,
                input: (_r = project.settings) === null || _r === void 0 ? void 0 : _r.input,
            },
            scenes: project.scenes.map((s) => this.convertNiceSceneToNdg(s)),
            assets: project.assets.map((a) => this.convertNiceAssetToNdg(a)),
        };
    }
    convertNiceAssetToNdg(asset) {
        return {
            id: asset.id,
            name: asset.name,
            type: asset.type,
            path: asset.path,
            data: asset.data,
        };
    }
    extractMetadata(settings) {
        const knownKeys = ['width', 'height', 'backgroundColor', 'gravity'];
        const metadata = {};
        for (const [key, value] of Object.entries(settings)) {
            if (!knownKeys.includes(key)) {
                metadata[key] = value;
            }
        }
        return Object.keys(metadata).length > 0 ? metadata : {};
    }
}
// ============================================================
// Bidirectional Sync Helper
// ============================================================
class NdgBidirectionalSync {
    constructor() {
        this.importer = new NdgImporter();
        this.exporter = new NdgExporter();
    }
    /**
     * Import and track original data for round-trip
     */
    async importWithTracking(sourcePath, sourceType) {
        const result = await this.importer.import({ sourcePath });
        const source = {
            type: sourceType,
            path: sourcePath,
            importedAt: new Date().toISOString(),
            // Could also preserve original data here for lossless round-trip
        };
        return {
            scenes: result.scenes,
            assets: result.assets,
            source,
        };
    }
    /**
     * Export with source tracking for later re-import
     */
    exportWithTracking(scene, source) {
        const ndgFile = this.exporter.exportScene(scene, source);
        return this.exporter.serialize(ndgFile);
    }
    /**
     * Check if NDG file has modifications compared to source
     */
    hasModifications(ndgFile) {
        return ndgFile.created !== ndgFile.modified;
    }
    /**
     * Update the modified timestamp
     */
    touch(ndgFile) {
        return {
            ...ndgFile,
            modified: new Date().toISOString(),
        };
    }
}
// ============================================================
// Factory Functions
// ============================================================
/**
 * Create NDG importer
 */
function createNdgImporter() {
    return new NdgImporter();
}
/**
 * Create NDG exporter
 */
function createNdgExporter() {
    return new NdgExporter();
}
/**
 * Create bidirectional sync helper
 */
function createBidirectionalSync() {
    return new NdgBidirectionalSync();
}
/**
 * Quick export scene to NDG JSON string
 */
function sceneToNdg(scene, pretty = true) {
    const exporter = new NdgExporter();
    const ndgFile = exporter.exportScene(scene);
    return exporter.serialize(ndgFile, pretty);
}
/**
 * Quick import NDG JSON string to scene
 */
async function ndgToScene(ndgJson) {
    try {
        const ndgFile = JSON.parse(ndgJson);
        if (ndgFile.magic !== NDG_MAGIC || ndgFile.type !== 'scene') {
            return null;
        }
        const importer = new NdgImporter();
        const result = await importer.parseFile(ndgJson, 'inline.ndg');
        if (result && 'name' in result) {
            return importer['convertParsedToNiceScene'](result);
        }
        return null;
    }
    catch (_a) {
        return null;
    }
}

export { NdgBidirectionalSync, NdgExporter, NdgImporter, createBidirectionalSync, createNdgExporter, createNdgImporter, ndgToScene, sceneToNdg };
//# sourceMappingURL=NdgFormat.js.map
