'use strict';

var PlatformExporter = require('./PlatformExporter.js');
var GDScriptExporter = require('../scripting/exporters/GDScriptExporter.js');
var GraphToAST = require('../scripting/GraphToAST.js');

/* ────────────────────────────────────────────────────────────────
   Godot Project Exporter
   
   Exports Nice2Dev projects to Godot 4.x format.
   Generates .tscn scenes, .tres resources, and .gd scripts.
──────────────────────────────────────────────────────────────── */
/* ── Godot Exporter Class ─────────────────────────────────────── */
class GodotExporter extends PlatformExporter.PlatformExporter {
    constructor() {
        super(...arguments);
        this.platformId = 'godot';
        this.platformInfo = {
            id: 'godot',
            name: 'Godot Engine',
            description: 'Free and open source game engine',
            website: 'https://godotengine.org',
            features: [
                '2d-rendering',
                '3d-rendering',
                'physics-2d',
                'physics-3d',
                'audio',
                'networking',
                'ui-system',
                'visual-scripting',
                'tilemaps',
                'particles',
                'animation',
            ],
            supportedAssets: [
                'sprite',
                'tileset',
                'audio',
                'font',
                'script',
                'scene',
                'prefab',
                'material',
                'shader',
                'animation',
                'tilemap',
                'particleSystem',
            ],
            exportFormats: ['.tscn', '.tres', '.gd', '.godot'],
        };
        this.gdscriptExporter = new GDScriptExporter.GDScriptExporter();
        this.graphToAST = new GraphToAST.GraphToAST();
        this.resourceIdCounter = 1;
        this.uidCounter = 1;
    }
    async doExport(project, options) {
        const godot = options.platformOptions;
        const projectName = options.projectName || project.name;
        // 1. Generate project.godot
        this.exportProjectFile(project, projectName, godot);
        // 2. Export scripts
        await this.exportScripts(project, options, godot);
        // 3. Export scenes (.tscn)
        await this.exportScenes(project, options);
        // 4. Export prefabs as packed scenes
        await this.exportPrefabs(project, options);
        // 5. Export resources (.tres)
        await this.exportResources(project, options);
        // 6. Export tilemaps and tilesets
        await this.exportTilesets(project, options);
        // 7. Generate autoload singletons
        if ((godot === null || godot === void 0 ? void 0 : godot.includeAutoloads) !== false) {
            this.exportAutoloads(project, projectName);
        }
        // 8. Export default_env.tres
        this.exportEnvironment(project);
        // 9. Generate import files for assets
        this.exportAssetImports(project);
    }
    /* ── Project File ───────────────────────────────────────────── */
    exportProjectFile(project, projectName, godot) {
        var _a, _b, _c, _d, _e, _f;
        const version = (godot === null || godot === void 0 ? void 0 : godot.godotVersion) || '4.2';
        const renderer = (godot === null || godot === void 0 ? void 0 : godot.renderer) || 'forward_plus';
        const content = `; Engine configuration file.
; It's best edited using the editor UI and not directly,
; since the parameters that go here are not all obvious.
;
; Format:
;   [section] ; section goes between []
;   param=value ; assign values to parameters

config_version=5

[application]

config/name="${project.name}"
config/description="${project.description || ''}"
config/version="${project.version}"
run/main_scene="res://scenes/${this.sanitizeName(((_a = project.scenes[0]) === null || _a === void 0 ? void 0 : _a.name) || 'main')}.tscn"
config/features=PackedStringArray("${version}", "Forward Plus")
config/icon="res://icon.svg"

[autoload]

GameManager="*res://scripts/autoload/GameManager.gd"
AudioManager="*res://scripts/autoload/AudioManager.gd"
EventBus="*res://scripts/autoload/EventBus.gd"

[display]

window/size/viewport_width=${project.settings.resolution.width}
window/size/viewport_height=${project.settings.resolution.height}
window/stretch/mode="canvas_items"
window/stretch/aspect="keep"

[input]

move_left={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"echo":false,"script":null)]
}
move_right={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"echo":false,"script":null)]
}
move_up={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":87,"key_label":0,"unicode":119,"echo":false,"script":null)]
}
move_down={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":83,"key_label":0,"unicode":115,"echo":false,"script":null)]
}
jump={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"echo":false,"script":null)]
}
action={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":69,"key_label":0,"unicode":101,"echo":false,"script":null)]
}

[layer_names]

2d_physics/layer_1="player"
2d_physics/layer_2="enemies"
2d_physics/layer_3="world"
2d_physics/layer_4="projectiles"
2d_physics/layer_5="pickups"

[physics]

2d/default_gravity=${(_c = (_b = project.settings.physics) === null || _b === void 0 ? void 0 : _b.gravity.y) !== null && _c !== void 0 ? _c : 980}
2d/default_gravity_vector=Vector2(${(_e = (_d = project.settings.physics) === null || _d === void 0 ? void 0 : _d.gravity.x) !== null && _e !== void 0 ? _e : 0}, 1)

[rendering]

renderer/rendering_method="${renderer}"
textures/canvas_textures/default_texture_filter=${((_f = project.settings.rendering) === null || _f === void 0 ? void 0 : _f.pixelArt) ? 0 : 1}
environment/defaults/default_clear_color=Color(${this.hexToGodotColor(project.settings.backgroundColor)})
`;
        this.addTextFile('project.godot', content);
    }
    /* ── Scripts ────────────────────────────────────────────────── */
    async exportScripts(project, options, godot) {
        for (const script of project.scripts) {
            try {
                const ast = this.graphToAST.convert(script);
                const result = this.gdscriptExporter.export(ast, {
                    includeDebugComments: options.debug,
                });
                for (const file of result.files) {
                    const path = `scripts/${file.path}`;
                    this.addTextFile(path, file.content);
                }
            }
            catch (error) {
                this.addWarning('SCRIPT_EXPORT_ERROR', `Failed to export script "${script.name}": ${error}`, 'Check visual script for errors');
            }
        }
    }
    /* ── Scenes ─────────────────────────────────────────────────── */
    async exportScenes(project, options) {
        for (const scene of project.scenes) {
            const tscn = this.createSceneTSCN(scene, project);
            const path = `scenes/${this.sanitizeName(scene.name)}.tscn`;
            this.addTextFile(path, tscn);
        }
    }
    createSceneTSCN(scene, project) {
        var _a;
        const resources = [];
        const nodes = [];
        // Root node
        const rootNode = {
            name: scene.name,
            type: 'Node2D',
            properties: {},
            children: [],
        };
        // Process entities
        for (const entity of scene.entities) {
            const node = this.createGodotNode(entity, project, resources);
            rootNode.children.push(node);
        }
        // Process tilemaps
        for (const tilemap of (_a = scene.tilemaps) !== null && _a !== void 0 ? _a : []) {
            const tilemapNode = this.createTilemapNode(tilemap, project, resources);
            rootNode.children.push(tilemapNode);
        }
        nodes.push(rootNode);
        return this.serializeTSCN(resources, nodes, scene.name);
    }
    createGodotNode(entity, project, resources) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
        // Determine node type based on components
        let nodeType = 'Node2D';
        const properties = {};
        // Check for specific node types
        entity.components.some((c) => c.type === 'sprite');
        const hasRigidbody = entity.components.some((c) => c.type === 'rigidbody-2d');
        const hasCharacterBody = entity.components.some((c) => c.type === 'character-body-2d');
        const hasArea = entity.components.some((c) => c.type === 'area-2d');
        const isUI = entity.components.some((c) => c.type.startsWith('ui-'));
        if (hasCharacterBody) {
            nodeType = 'CharacterBody2D';
        }
        else if (hasRigidbody) {
            nodeType = 'RigidBody2D';
        }
        else if (hasArea) {
            nodeType = 'Area2D';
        }
        else if (isUI) {
            nodeType = 'Control';
        }
        // Set transform
        properties.position = `Vector2(${(_b = (_a = entity.position) === null || _a === void 0 ? void 0 : _a.x) !== null && _b !== void 0 ? _b : 0}, ${(_d = (_c = entity.position) === null || _c === void 0 ? void 0 : _c.y) !== null && _d !== void 0 ? _d : 0})`;
        properties.rotation = (_e = entity.rotation) !== null && _e !== void 0 ? _e : 0;
        properties.scale = `Vector2(${(_g = (_f = entity.scale) === null || _f === void 0 ? void 0 : _f.x) !== null && _g !== void 0 ? _g : 1}, ${(_j = (_h = entity.scale) === null || _h === void 0 ? void 0 : _h.y) !== null && _j !== void 0 ? _j : 1})`;
        const node = {
            name: entity.name,
            type: nodeType,
            properties,
            children: [],
        };
        // Add child nodes for components
        for (const component of entity.components) {
            const childNode = this.createComponentNode(component, entity, project, resources);
            if (childNode) {
                node.children.push(childNode);
            }
        }
        // Add script if present
        if (entity.scriptId) {
            const script = project.scripts.find((s) => s.id === entity.scriptId);
            if (script) {
                properties.script = `ExtResource("${this.addScriptResource(script, resources)}")`;
            }
        }
        // Process children entities
        if (entity.children) {
            for (const child of entity.children) {
                const childNode = this.createGodotNode(child, project, resources);
                node.children.push(childNode);
            }
        }
        // Handle prefab instances
        if (entity.prefabId) {
            const prefab = project.prefabs.find((p) => p.id === entity.prefabId);
            if (prefab) {
                return {
                    name: entity.name,
                    type: 'Node2D',
                    instance: `res://prefabs/${this.sanitizeName(prefab.name)}.tscn`,
                    properties: {
                        position: `Vector2(${(_l = (_k = entity.position) === null || _k === void 0 ? void 0 : _k.x) !== null && _l !== void 0 ? _l : 0}, ${(_o = (_m = entity.position) === null || _m === void 0 ? void 0 : _m.y) !== null && _o !== void 0 ? _o : 0})`,
                    },
                };
            }
        }
        return node;
    }
    createComponentNode(component, entity, project, resources) {
        var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _0, _1, _2, _3, _4, _5;
        const props = (_a = component.properties) !== null && _a !== void 0 ? _a : {};
        switch (component.type) {
            case 'sprite': {
                const spriteId = props.spriteId;
                const sprite = project.assets.find((a) => a.id === spriteId);
                const textureResId = sprite ? this.addTextureResource(sprite, resources) : null;
                return {
                    name: 'Sprite2D',
                    type: 'Sprite2D',
                    properties: {
                        texture: textureResId ? `ExtResource("${textureResId}")` : 'null',
                        flip_h: props.flipX || false,
                        flip_v: props.flipY || false,
                        modulate: props.color
                            ? `Color(${this.hexToGodotColor(props.color)})`
                            : undefined,
                    },
                };
            }
            case 'animated-sprite': {
                return {
                    name: 'AnimatedSprite2D',
                    type: 'AnimatedSprite2D',
                    properties: {
                        autoplay: props.autoplay,
                        frame: (_b = props.frame) !== null && _b !== void 0 ? _b : 0,
                        speed_scale: (_c = props.speedScale) !== null && _c !== void 0 ? _c : 1,
                    },
                };
            }
            case 'box-collider-2d': {
                const shapeId = this.nextResourceId();
                resources.push({
                    type: 'RectangleShape2D',
                    id: shapeId,
                    properties: {
                        size: `Vector2(${(_d = props.width) !== null && _d !== void 0 ? _d : 32}, ${(_e = props.height) !== null && _e !== void 0 ? _e : 32})`,
                    },
                });
                return {
                    name: 'CollisionShape2D',
                    type: 'CollisionShape2D',
                    properties: {
                        shape: `SubResource("${shapeId}")`,
                        position: `Vector2(${(_f = props.offsetX) !== null && _f !== void 0 ? _f : 0}, ${(_g = props.offsetY) !== null && _g !== void 0 ? _g : 0})`,
                        disabled: props.disabled || false,
                    },
                };
            }
            case 'circle-collider-2d': {
                const shapeId = this.nextResourceId();
                resources.push({
                    type: 'CircleShape2D',
                    id: shapeId,
                    properties: {
                        radius: (_h = props.radius) !== null && _h !== void 0 ? _h : 16,
                    },
                });
                return {
                    name: 'CollisionShape2D',
                    type: 'CollisionShape2D',
                    properties: {
                        shape: `SubResource("${shapeId}")`,
                        position: `Vector2(${(_j = props.offsetX) !== null && _j !== void 0 ? _j : 0}, ${(_k = props.offsetY) !== null && _k !== void 0 ? _k : 0})`,
                    },
                };
            }
            case 'capsule-collider-2d': {
                const shapeId = this.nextResourceId();
                resources.push({
                    type: 'CapsuleShape2D',
                    id: shapeId,
                    properties: {
                        radius: (_l = props.radius) !== null && _l !== void 0 ? _l : 16,
                        height: (_m = props.height) !== null && _m !== void 0 ? _m : 64,
                    },
                });
                return {
                    name: 'CollisionShape2D',
                    type: 'CollisionShape2D',
                    properties: {
                        shape: `SubResource("${shapeId}")`,
                    },
                };
            }
            case 'audio-source': {
                const clipId = props.clipId;
                const clip = project.assets.find((a) => a.id === clipId);
                const audioResId = clip ? this.addAudioResource(clip, resources) : null;
                return {
                    name: 'AudioStreamPlayer2D',
                    type: props.is3D ? 'AudioStreamPlayer3D' : 'AudioStreamPlayer2D',
                    properties: {
                        stream: audioResId ? `ExtResource("${audioResId}")` : 'null',
                        autoplay: props.playOnAwake || false,
                        volume_db: props.volume !== undefined ? this.linearToDb(props.volume) : 0,
                        pitch_scale: (_o = props.pitch) !== null && _o !== void 0 ? _o : 1,
                        max_distance: (_p = props.maxDistance) !== null && _p !== void 0 ? _p : 2000,
                    },
                };
            }
            case 'particle-system': {
                return {
                    name: 'GPUParticles2D',
                    type: 'GPUParticles2D',
                    properties: {
                        emitting: props.playOnAwake !== false,
                        amount: (_q = props.maxParticles) !== null && _q !== void 0 ? _q : 100,
                        lifetime: (_r = props.duration) !== null && _r !== void 0 ? _r : 1,
                        one_shot: !props.looping,
                        preprocess: props.prewarm ? ((_s = props.duration) !== null && _s !== void 0 ? _s : 1) : 0,
                        speed_scale: (_t = props.speedScale) !== null && _t !== void 0 ? _t : 1,
                    },
                };
            }
            case 'camera': {
                return {
                    name: 'Camera2D',
                    type: 'Camera2D',
                    properties: {
                        current: props.isMain || false,
                        zoom: `Vector2(${(_u = props.zoom) !== null && _u !== void 0 ? _u : 1}, ${(_v = props.zoom) !== null && _v !== void 0 ? _v : 1})`,
                        position_smoothing_enabled: props.smoothing || false,
                        position_smoothing_speed: (_w = props.smoothingSpeed) !== null && _w !== void 0 ? _w : 5,
                        drag_horizontal_enabled: props.dragEnabled || false,
                        drag_vertical_enabled: props.dragEnabled || false,
                    },
                };
            }
            case 'ui-text': {
                return {
                    name: 'Label',
                    type: 'Label',
                    properties: {
                        text: (_x = props.text) !== null && _x !== void 0 ? _x : '',
                        horizontal_alignment: this.getHorizontalAlignment(props.alignment),
                        vertical_alignment: this.getVerticalAlignment(props.alignment),
                    },
                };
            }
            case 'ui-button': {
                return {
                    name: 'Button',
                    type: 'Button',
                    properties: {
                        text: (_y = props.text) !== null && _y !== void 0 ? _y : 'Button',
                        disabled: props.disabled || false,
                    },
                };
            }
            case 'ui-image': {
                const spriteId = props.spriteId;
                const sprite = project.assets.find((a) => a.id === spriteId);
                const textureResId = sprite ? this.addTextureResource(sprite, resources) : null;
                return {
                    name: 'TextureRect',
                    type: 'TextureRect',
                    properties: {
                        texture: textureResId ? `ExtResource("${textureResId}")` : 'null',
                        expand_mode: 1, // ExpandMode.IGNORE_SIZE
                        stretch_mode: 5, // StretchMode.KEEP_ASPECT_CENTERED
                    },
                };
            }
            case 'raycast': {
                return {
                    name: 'RayCast2D',
                    type: 'RayCast2D',
                    properties: {
                        enabled: true,
                        target_position: `Vector2(${(_0 = (_z = props.direction) === null || _z === void 0 ? void 0 : _z.x) !== null && _0 !== void 0 ? _0 : 0}, ${(_2 = (_1 = props.direction) === null || _1 === void 0 ? void 0 : _1.y) !== null && _2 !== void 0 ? _2 : 50})`,
                        collision_mask: (_3 = props.collisionMask) !== null && _3 !== void 0 ? _3 : 1,
                    },
                };
            }
            case 'light-2d': {
                return {
                    name: 'PointLight2D',
                    type: 'PointLight2D',
                    properties: {
                        enabled: props.enabled !== false,
                        color: props.color
                            ? `Color(${this.hexToGodotColor(props.color)})`
                            : 'Color(1, 1, 1, 1)',
                        energy: (_4 = props.intensity) !== null && _4 !== void 0 ? _4 : 1,
                        texture_scale: (_5 = props.range) !== null && _5 !== void 0 ? _5 : 1,
                    },
                };
            }
            default:
                // Skip unknown components
                return null;
        }
    }
    /* ── Tilemaps ───────────────────────────────────────────────── */
    createTilemapNode(tilemap, project, resources) {
        const tilesetAsset = project.assets.find((a) => a.id === tilemap.tilesetId);
        const tilesetResId = tilesetAsset
            ? this.addTileSetResource(tilesetAsset, tilemap, resources)
            : null;
        return {
            name: tilemap.name,
            type: 'TileMap',
            properties: {
                tile_set: tilesetResId ? `ExtResource("${tilesetResId}")` : 'null',
                cell_quadrant_size: tilemap.tileSize,
            },
            children: tilemap.layers.map((layer, index) => ({
                name: layer.name,
                type: 'TileMapLayer',
                properties: {
                    visible: layer.visible,
                    modulate: `Color(1, 1, 1, ${layer.opacity})`,
                    z_index: index,
                },
            })),
        };
    }
    /* ── Prefabs ────────────────────────────────────────────────── */
    async exportPrefabs(project, options) {
        for (const prefab of project.prefabs) {
            const tscn = this.createPrefabTSCN(prefab, project);
            const path = `prefabs/${this.sanitizeName(prefab.name)}.tscn`;
            this.addTextFile(path, tscn);
        }
    }
    createPrefabTSCN(prefab, project) {
        const resources = [];
        const rootNode = this.createGodotNode(prefab.entity, project, resources);
        rootNode.name = prefab.name;
        return this.serializeTSCN(resources, [rootNode], prefab.name);
    }
    /* ── Resources ──────────────────────────────────────────────── */
    async exportResources(project, options) {
        // Export materials as ShaderMaterial resources
        const materials = project.assets.filter((a) => a.type === 'material');
        for (const material of materials) {
            const tres = this.createMaterialTRES(material);
            const path = `resources/materials/${this.sanitizeName(material.name)}.tres`;
            this.addTextFile(path, tres);
        }
        // Export animations as AnimationLibrary
        const animations = project.assets.filter((a) => a.type === 'animation');
        if (animations.length > 0) {
            const animLib = this.createAnimationLibrary(animations);
            this.addTextFile('resources/animations/animation_library.tres', animLib);
        }
    }
    createMaterialTRES(material) {
        var _a, _b;
        const color = (_b = (_a = material.metadata) === null || _a === void 0 ? void 0 : _a.color) !== null && _b !== void 0 ? _b : '#ffffff';
        return `[gd_resource type="ShaderMaterial" format=3]

[resource]
shader = null
shader_parameter/color = Color(${this.hexToGodotColor(color)})
`;
    }
    createAnimationLibrary(animations) {
        var _a, _b, _c;
        let content = `[gd_resource type="AnimationLibrary" format=3]

`;
        for (const anim of animations) {
            const frameRate = (_b = (_a = anim.metadata) === null || _a === void 0 ? void 0 : _a.frameRate) !== null && _b !== void 0 ? _b : 12;
            content += `[sub_resource type="Animation" id="${this.nextResourceId()}"]
resource_name = "${anim.name}"
length = ${((_c = anim.metadata) === null || _c === void 0 ? void 0 : _c.length) || 1.0}
step = ${1 / frameRate}

`;
        }
        content += `[resource]
_data = {
`;
        for (const anim of animations) {
            content += `"${anim.name}": SubResource("${this.resourceIdCounter - animations.length + animations.indexOf(anim)}"),
`;
        }
        content += `}`;
        return content;
    }
    /* ── Tilesets ───────────────────────────────────────────────── */
    async exportTilesets(project, options) {
        const tilesets = project.assets.filter((a) => a.type === 'tileset');
        for (const tileset of tilesets) {
            const tres = this.createTileSetTRES(tileset);
            const path = `resources/tilesets/${this.sanitizeName(tileset.name)}.tres`;
            this.addTextFile(path, tres);
        }
    }
    createTileSetTRES(tileset) {
        var _a, _b, _c, _d;
        const tileSize = (_b = (_a = tileset.metadata) === null || _a === void 0 ? void 0 : _a.tileSize) !== null && _b !== void 0 ? _b : 16;
        (_d = (_c = tileset.metadata) === null || _c === void 0 ? void 0 : _c.columns) !== null && _d !== void 0 ? _d : 8;
        return `[gd_resource type="TileSet" load_steps=2 format=3 uid="uid://${this.nextUID()}"]

[ext_resource type="Texture2D" path="res://assets/tilesets/${tileset.name}" id="1"]

[resource]
tile_shape = 0
tile_size = Vector2i(${tileSize}, ${tileSize})
sources/0/texture = ExtResource("1")
sources/0/texture_region_size = Vector2i(${tileSize}, ${tileSize})
`;
    }
    /* ── Autoloads ──────────────────────────────────────────────── */
    exportAutoloads(project, projectName) {
        // GameManager autoload
        const gameManager = `extends Node
class_name GameManager

## Game Manager singleton for Nice2Dev exported project.
## Handles global game state and entity registry.

signal game_started
signal game_paused
signal game_resumed
signal game_over

var entities: Dictionary = {}
var is_paused: bool = false
var score: int = 0
var level: int = 1

func _ready() -> void:
	process_mode = Node.PROCESS_MODE_ALWAYS

func register_entity(id: String, entity: Node) -> void:
	entities[id] = entity

func unregister_entity(id: String) -> void:
	entities.erase(id)

func get_entity(id: String) -> Node:
	return entities.get(id)

func pause_game() -> void:
	if not is_paused:
		is_paused = true
		get_tree().paused = true
		game_paused.emit()

func resume_game() -> void:
	if is_paused:
		is_paused = false
		get_tree().paused = false
		game_resumed.emit()

func toggle_pause() -> void:
	if is_paused:
		resume_game()
	else:
		pause_game()

func start_game() -> void:
	score = 0
	level = 1
	is_paused = false
	get_tree().paused = false
	game_started.emit()

func end_game() -> void:
	game_over.emit()

func add_score(amount: int) -> void:
	score += amount

func next_level() -> void:
	level += 1
`;
        this.addTextFile('scripts/autoload/GameManager.gd', gameManager);
        // AudioManager autoload
        const audioManager = `extends Node
class_name AudioManager

## Audio Manager singleton for Nice2Dev exported project.
## Handles music and sound effect playback.

var music_player: AudioStreamPlayer
var sfx_players: Array[AudioStreamPlayer] = []
var music_volume: float = 1.0
var sfx_volume: float = 1.0
var master_volume: float = 1.0

const MAX_SFX_PLAYERS = 8

func _ready() -> void:
	music_player = AudioStreamPlayer.new()
	music_player.bus = "Music"
	add_child(music_player)
	
	for i in MAX_SFX_PLAYERS:
		var player = AudioStreamPlayer.new()
		player.bus = "SFX"
		add_child(player)
		sfx_players.append(player)

func play_music(stream: AudioStream, fade_in: float = 0.5) -> void:
	if music_player.playing:
		var tween = create_tween()
		tween.tween_property(music_player, "volume_db", -80.0, fade_in)
		await tween.finished
	
	music_player.stream = stream
	music_player.volume_db = linear_to_db(music_volume * master_volume)
	music_player.play()

func stop_music(fade_out: float = 0.5) -> void:
	if music_player.playing:
		var tween = create_tween()
		tween.tween_property(music_player, "volume_db", -80.0, fade_out)
		await tween.finished
		music_player.stop()

func play_sfx(stream: AudioStream, volume: float = 1.0, pitch: float = 1.0) -> void:
	var player = _get_available_sfx_player()
	if player:
		player.stream = stream
		player.volume_db = linear_to_db(volume * sfx_volume * master_volume)
		player.pitch_scale = pitch
		player.play()

func _get_available_sfx_player() -> AudioStreamPlayer:
	for player in sfx_players:
		if not player.playing:
			return player
	return sfx_players[0]  # Fallback to first

func set_master_volume(volume: float) -> void:
	master_volume = clamp(volume, 0.0, 1.0)
	_update_volumes()

func set_music_volume(volume: float) -> void:
	music_volume = clamp(volume, 0.0, 1.0)
	_update_volumes()

func set_sfx_volume(volume: float) -> void:
	sfx_volume = clamp(volume, 0.0, 1.0)

func _update_volumes() -> void:
	music_player.volume_db = linear_to_db(music_volume * master_volume)
`;
        this.addTextFile('scripts/autoload/AudioManager.gd', audioManager);
        // EventBus autoload
        const eventBus = `extends Node
class_name EventBus

## Event Bus singleton for Nice2Dev exported project.
## Provides global event communication between nodes.

# Gameplay events
signal player_spawned(player: Node)
signal player_died(player: Node)
signal enemy_spawned(enemy: Node)
signal enemy_died(enemy: Node)
signal item_collected(item: Node, collector: Node)
signal damage_dealt(target: Node, amount: float, source: Node)

# UI events
signal ui_button_pressed(button_id: String)
signal dialog_started(dialog_id: String)
signal dialog_ended(dialog_id: String)

# Level events
signal level_started(level_id: String)
signal level_completed(level_id: String)
signal checkpoint_reached(checkpoint_id: String)

# Custom events dictionary for dynamic events
var _custom_handlers: Dictionary = {}

func emit_custom(event_name: String, data: Variant = null) -> void:
	if _custom_handlers.has(event_name):
		for handler in _custom_handlers[event_name]:
			if is_instance_valid(handler.object):
				handler.object.call(handler.method, data)

func subscribe(event_name: String, object: Object, method: String) -> void:
	if not _custom_handlers.has(event_name):
		_custom_handlers[event_name] = []
	_custom_handlers[event_name].append({"object": object, "method": method})

func unsubscribe(event_name: String, object: Object, method: String) -> void:
	if _custom_handlers.has(event_name):
		_custom_handlers[event_name] = _custom_handlers[event_name].filter(
			func(h): return h.object != object or h.method != method
		)
`;
        this.addTextFile('scripts/autoload/EventBus.gd', eventBus);
    }
    /* ── Environment ────────────────────────────────────────────── */
    exportEnvironment(project) {
        const bgColor = this.hexToGodotColor(project.settings.backgroundColor);
        const env = `[gd_resource type="Environment" format=3]

[resource]
background_mode = 1
background_color = Color(${bgColor})
`;
        this.addTextFile('resources/default_env.tres', env);
    }
    /* ── Asset Imports ──────────────────────────────────────────── */
    exportAssetImports(project) {
        for (const asset of project.assets) {
            const importFile = this.createImportFile(asset);
            if (importFile) {
                const assetPath = this.getAssetPath(asset);
                this.addTextFile(`${assetPath}.import`, importFile);
            }
        }
    }
    createImportFile(asset) {
        switch (asset.type) {
            case 'sprite':
                return `[remap]

importer="texture"
type="CompressedTexture2D"
uid="uid://${this.nextUID()}"
path="res://.godot/imported/${asset.name}.ctex"

[deps]

source_file="res://assets/sprites/${asset.name}"
dest_files=["res://.godot/imported/${asset.name}.ctex"]

[params]

compress/mode=0
compress/high_quality=false
compress/lossy_quality=0.7
compress/hdr_compression=1
compress/normal_map=0
compress/channel_pack=0
mipmaps/generate=false
mipmaps/limit=-1
roughness/mode=0
roughness/src_normal=""
process/fix_alpha_border=true
process/premult_alpha=false
process/normal_map_invert_y=false
process/hdr_as_srgb=false
process/hdr_clamp_exposure=false
process/size_limit=0
detect_3d/compress_to=1
`;
            case 'audio':
                return `[remap]

importer="wav"
type="AudioStreamWAV"
uid="uid://${this.nextUID()}"
path="res://.godot/imported/${asset.name}.sample"

[deps]

source_file="res://assets/audio/${asset.name}"
dest_files=["res://.godot/imported/${asset.name}.sample"]

[params]

force/8_bit=false
force/mono=false
force/max_rate=false
force/max_rate_hz=44100
edit/trim=false
edit/normalize=false
edit/loop_mode=0
edit/loop_begin=0
edit/loop_end=-1
compress/mode=0
`;
            case 'font':
                return `[remap]

importer="font_data_dynamic"
type="FontFile"
uid="uid://${this.nextUID()}"
path="res://.godot/imported/${asset.name}.fontdata"

[deps]

source_file="res://assets/fonts/${asset.name}"
dest_files=["res://.godot/imported/${asset.name}.fontdata"]

[params]

Rendering=null
antialiasing=1
generate_mipmaps=false
multichannel_signed_distance_field=false
msdf_pixel_range=8
msdf_size=48
allow_system_fallback=true
force_autohinter=false
hinting=1
subpixel_positioning=1
oversampling=0.0
Fallbacks=null
fallbacks=[]
Compress=null
compress=true
preload=[]
language_support={}
script_support={}
opentype_features={}
`;
            default:
                return null;
        }
    }
    getAssetPath(asset) {
        switch (asset.type) {
            case 'sprite':
                return `assets/sprites/${asset.name}`;
            case 'audio':
                return `assets/audio/${asset.name}`;
            case 'font':
                return `assets/fonts/${asset.name}`;
            case 'tileset':
                return `assets/tilesets/${asset.name}`;
            default:
                return `assets/${asset.name}`;
        }
    }
    /* ── Resource Helpers ───────────────────────────────────────── */
    addScriptResource(script, resources) {
        const id = this.nextResourceId().toString();
        resources.push({
            type: 'GDScript',
            id,
            path: `res://scripts/${this.sanitizeName(script.name)}.gd`,
            properties: {},
        });
        return id;
    }
    addTextureResource(asset, resources) {
        const id = this.nextResourceId().toString();
        resources.push({
            type: 'Texture2D',
            id,
            path: `res://assets/sprites/${asset.name}`,
            properties: {},
        });
        return id;
    }
    addAudioResource(asset, resources) {
        const id = this.nextResourceId().toString();
        resources.push({
            type: 'AudioStream',
            id,
            path: `res://assets/audio/${asset.name}`,
            properties: {},
        });
        return id;
    }
    addTileSetResource(asset, tilemap, resources) {
        const id = this.nextResourceId().toString();
        resources.push({
            type: 'TileSet',
            id,
            path: `res://resources/tilesets/${this.sanitizeName(asset.name)}.tres`,
            properties: {},
        });
        return id;
    }
    /* ── TSCN Serialization ─────────────────────────────────────── */
    serializeTSCN(resources, nodes, sceneName) {
        const extResources = resources.filter((r) => r.path);
        const subResources = resources.filter((r) => !r.path);
        const loadSteps = extResources.length + subResources.length + 1;
        let output = `[gd_scene load_steps=${loadSteps} format=3 uid="uid://${this.nextUID()}"]

`;
        // External resources
        for (const res of extResources) {
            output += `[ext_resource type="${res.type}" path="${res.path}" id="${res.id}"]\n`;
        }
        if (extResources.length > 0)
            output += '\n';
        // Sub-resources
        for (const res of subResources) {
            output += `[sub_resource type="${res.type}" id="${res.id}"]\n`;
            for (const [key, value] of Object.entries(res.properties)) {
                if (value !== undefined) {
                    output += `${key} = ${this.formatValue(value)}\n`;
                }
            }
            output += '\n';
        }
        // Nodes
        output += this.serializeNodes(nodes);
        return output;
    }
    serializeNodes(nodes, parent) {
        let output = '';
        for (const node of nodes) {
            if (node.instance) {
                // Instance of packed scene
                output += `[node name="${node.name}" parent="${parent || '.'}" instance=ExtResource("${node.instance}")]\n`;
            }
            else if (!parent) {
                // Root node
                output += `[node name="${node.name}" type="${node.type}"]\n`;
            }
            else {
                output += `[node name="${node.name}" type="${node.type}" parent="${parent}"]\n`;
            }
            // Node properties
            for (const [key, value] of Object.entries(node.properties)) {
                if (value !== undefined && key !== 'script') {
                    output += `${key} = ${this.formatValue(value)}\n`;
                }
            }
            // Script last
            if (node.properties.script) {
                output += `script = ${node.properties.script}\n`;
            }
            output += '\n';
            // Children
            if (node.children && node.children.length > 0) {
                const nodePath = parent ? `${parent}/${node.name}` : '.';
                output += this.serializeNodes(node.children, nodePath);
            }
        }
        return output;
    }
    /* ── Utility Methods ────────────────────────────────────────── */
    formatValue(value) {
        if (typeof value === 'string') {
            if (value.startsWith('Vector2(') ||
                value.startsWith('Vector3(') ||
                value.startsWith('Color(') ||
                value.startsWith('ExtResource(') ||
                value.startsWith('SubResource(')) {
                return value;
            }
            return `"${value}"`;
        }
        if (typeof value === 'boolean') {
            return value ? 'true' : 'false';
        }
        if (typeof value === 'number') {
            return value.toString();
        }
        if (value === null) {
            return 'null';
        }
        return String(value);
    }
    hexToGodotColor(hex) {
        const clean = hex.replace('#', '');
        const r = parseInt(clean.slice(0, 2), 16) / 255;
        const g = parseInt(clean.slice(2, 4), 16) / 255;
        const b = parseInt(clean.slice(4, 6), 16) / 255;
        const a = clean.length > 6 ? parseInt(clean.slice(6, 8), 16) / 255 : 1;
        return `${r.toFixed(3)}, ${g.toFixed(3)}, ${b.toFixed(3)}, ${a.toFixed(3)}`;
    }
    linearToDb(linear) {
        if (linear <= 0)
            return -80;
        return 20 * Math.log10(linear);
    }
    sanitizeName(name) {
        return name.replace(/[^a-zA-Z0-9_]/g, '_');
    }
    nextResourceId() {
        return this.resourceIdCounter++;
    }
    nextUID() {
        return (this.uidCounter++).toString().padStart(12, '0');
    }
    getHorizontalAlignment(alignment) {
        switch (alignment) {
            case 'left':
            case 'top-left':
            case 'bottom-left':
                return 0;
            case 'center':
            case 'top-center':
            case 'bottom-center':
                return 1;
            case 'right':
            case 'top-right':
            case 'bottom-right':
                return 2;
            default:
                return 0;
        }
    }
    getVerticalAlignment(alignment) {
        switch (alignment) {
            case 'top':
            case 'top-left':
            case 'top-center':
            case 'top-right':
                return 0;
            case 'center':
            case 'left':
            case 'right':
                return 1;
            case 'bottom':
            case 'bottom-left':
            case 'bottom-center':
            case 'bottom-right':
                return 2;
            default:
                return 0;
        }
    }
}

exports.GodotExporter = GodotExporter;
//# sourceMappingURL=GodotExporter.js.map
