/**
 * Editor-Engine Sync Service
 * 编辑器-引擎同步服务
 *
 * Synchronizes editor entities to Rust engine for rendering.
 * 将编辑器实体同步到Rust引擎进行渲染。
 */

import { Entity, Component } from '@esengine/ecs-framework';
import { MessageHub, EntityStoreService } from '@esengine/editor-core';
import { TransformComponent, SpriteComponent, SpriteAnimatorComponent } from '@esengine/ecs-components';
import { EngineService } from './EngineService';

export class EditorEngineSync {
    private static instance: EditorEngineSync | null = null;

    private engineService: EngineService;
    private messageHub: MessageHub | null = null;
    private entityStore: EntityStoreService | null = null;

    // Track synced entities: editor entity id -> engine entity id
    private syncedEntities: Map<number, Entity> = new Map();

    // Subscription IDs
    private subscriptions: Array<() => void> = [];

    private initialized = false;

    private constructor() {
        this.engineService = EngineService.getInstance();
    }

    /**
     * Get singleton instance.
     * 获取单例实例。
     */
    static getInstance(): EditorEngineSync {
        if (!EditorEngineSync.instance) {
            EditorEngineSync.instance = new EditorEngineSync();
        }
        return EditorEngineSync.instance;
    }

    /**
     * Initialize sync service.
     * 初始化同步服务。
     */
    initialize(messageHub: MessageHub, entityStore: EntityStoreService): void {
        if (this.initialized) {
            return;
        }

        this.messageHub = messageHub;
        this.entityStore = entityStore;

        // Subscribe to entity events
        this.subscribeToEvents();

        // Sync existing entities
        this.syncAllEntities();

        this.initialized = true;
    }

    /**
     * Subscribe to MessageHub events.
     * 订阅MessageHub事件。
     */
    private subscribeToEvents(): void {
        if (!this.messageHub) return;

        // Entity added
        const unsubAdd = this.messageHub.subscribe('entity:added', (data: { entity: Entity }) => {
            this.syncEntity(data.entity);
        });
        this.subscriptions.push(unsubAdd);

        // Entity removed
        const unsubRemove = this.messageHub.subscribe('entity:removed', (data: { entity: Entity }) => {
            this.removeEntityFromEngine(data.entity);
        });
        this.subscriptions.push(unsubRemove);

        // Component property changed - need to re-sync entity
        const unsubComponent = this.messageHub.subscribe('component:property:changed', (data: { entity: Entity; component: Component; propertyName: string; value: any }) => {
            this.updateEntityInEngine(data.entity, data.component, data.propertyName, data.value);
        });
        this.subscriptions.push(unsubComponent);

        // Component added - sync entity if it has sprite
        const unsubComponentAdded = this.messageHub.subscribe('component:added', (data: { entity: Entity; component: Component }) => {
            this.syncEntity(data.entity);
        });
        this.subscriptions.push(unsubComponentAdded);

        // Entities cleared
        const unsubClear = this.messageHub.subscribe('entities:cleared', () => {
            this.clearAllFromEngine();
        });
        this.subscriptions.push(unsubClear);

        // Entity selected - update gizmo display
        const unsubSelected = this.messageHub.subscribe('entity:selected', (data: { entity: Entity | null }) => {
            this.updateSelectedEntity(data.entity);
        });
        this.subscriptions.push(unsubSelected);
    }

    /**
     * Update selected entity for gizmo display.
     * 更新选中的实体用于Gizmo显示。
     */
    private updateSelectedEntity(entity: Entity | null): void {
        if (entity) {
            this.engineService.setSelectedEntityIds([entity.id]);
        } else {
            this.engineService.setSelectedEntityIds([]);
        }
    }

    /**
     * Sync all existing entities.
     * 同步所有现有实体。
     */
    private syncAllEntities(): void {
        if (!this.entityStore) return;

        const entities = this.entityStore.getAllEntities();
        for (const entity of entities) {
            this.syncEntity(entity);
        }
    }

    /**
     * Sync a single entity to engine.
     * 将单个实体同步到引擎。
     *
     * Note: Texture loading is now handled automatically by EngineRenderSystem
     * via Rust engine's path-based texture loading.
     * 注意：纹理加载现在由EngineRenderSystem通过Rust引擎的路径加载自动处理。
     */
    private syncEntity(entity: Entity): void {
        // Check if entity has sprite component
        const spriteComponent = entity.getComponent(SpriteComponent);
        if (!spriteComponent) {
            return;
        }

        // Preload animator textures and set first frame
        // 预加载动画纹理并设置第一帧
        const animator = entity.getComponent(SpriteAnimatorComponent);
        if (animator && animator.clips) {
            const bridge = this.engineService.getBridge();
            if (bridge) {
                for (const clip of animator.clips) {
                    for (const frame of clip.frames) {
                        if (frame.texture) {
                            // Trigger texture loading
                            bridge.getOrLoadTextureByPath(frame.texture);
                        }
                    }
                }

                // Set sprite texture to first frame (static preview in editor)
                // 设置精灵纹理为第一帧（编辑器中的静态预览）
                if (animator.clips && animator.clips.length > 0) {
                    const firstClip = animator.clips[0];
                    if (firstClip && firstClip.frames && firstClip.frames.length > 0) {
                        const firstFrame = firstClip.frames[0];
                        if (firstFrame && firstFrame.texture && spriteComponent) {
                            spriteComponent.texture = firstFrame.texture;
                        }
                    }
                }
            }
        }

        // Track synced entity
        this.syncedEntities.set(entity.id, entity);
    }

    /**
     * Remove entity from tracking.
     * 从跟踪中移除实体。
     */
    private removeEntityFromEngine(entity: Entity): void {
        if (!entity) {
            return;
        }
        // Just remove from tracking, entity destruction is handled by the command
        this.syncedEntities.delete(entity.id);
    }

    /**
     * Update entity in engine when component changes.
     * 当组件变化时更新引擎中的实体。
     */
    private updateEntityInEngine(entity: Entity, component: Component, propertyName: string, value: any): void {
        const engineEntity = this.syncedEntities.get(entity.id);
        if (!engineEntity) {
            // Entity not synced yet, try to sync it
            this.syncEntity(entity);
            return;
        }

        // Update based on component type
        if (component instanceof TransformComponent) {
            this.updateTransform(engineEntity, component);
        } else if (component instanceof SpriteComponent) {
            this.updateSprite(engineEntity, component, propertyName, value);
        } else if (component instanceof SpriteAnimatorComponent) {
            this.updateAnimator(engineEntity, component, propertyName);
        }
    }

    /**
     * Update animator - preload textures and set initial frame.
     * 更新动画器 - 预加载纹理并设置初始帧。
     */
    private updateAnimator(entity: Entity, animator: SpriteAnimatorComponent, propertyName: string): void {
        // In editor mode, only preload textures and show first frame (no animation playback)
        // 编辑模式下只预加载纹理并显示第一帧（不播放动画）
        const bridge = this.engineService.getBridge();
        const sprite = entity.getComponent(SpriteComponent);

        if (bridge && animator.clips) {
            // Preload all frame textures
            for (const clip of animator.clips) {
                for (const frame of clip.frames) {
                    if (frame.texture) {
                        bridge.getOrLoadTextureByPath(frame.texture);
                    }
                }
            }

            // Set sprite texture to first frame if available (static preview in editor)
            // 设置精灵纹理为第一帧（编辑器中的静态预览）
            if (sprite && animator.clips && animator.clips.length > 0) {
                const firstClip = animator.clips[0];
                if (firstClip && firstClip.frames && firstClip.frames.length > 0) {
                    const firstFrame = firstClip.frames[0];
                    if (firstFrame && firstFrame.texture) {
                        sprite.texture = firstFrame.texture;
                    }
                }
            }
        }
    }

    /**
     * Update transform in engine entity.
     * 更新引擎实体的变换。
     */
    private updateTransform(engineEntity: Entity, transform: TransformComponent): void {
        // Get engine transform component (same type as editor)
        const engineTransform = engineEntity.getComponent(TransformComponent);
        if (engineTransform) {
            engineTransform.position = {
                x: transform.position?.x ?? 0,
                y: transform.position?.y ?? 0,
                z: transform.position?.z ?? 0
            };
            engineTransform.rotation = {
                x: transform.rotation?.x ?? 0,
                y: transform.rotation?.y ?? 0,
                z: transform.rotation?.z ?? 0
            };
            engineTransform.scale = {
                x: transform.scale?.x ?? 1,
                y: transform.scale?.y ?? 1,
                z: transform.scale?.z ?? 1
            };
        }
    }

    /**
     * Update sprite in engine entity.
     * 更新引擎实体的精灵。
     *
     * Note: Texture loading is now handled automatically by EngineRenderSystem.
     * 注意：纹理加载现在由EngineRenderSystem自动处理。
     */
    private updateSprite(entity: Entity, sprite: SpriteComponent, property: string, value: any): void {
        // No manual texture loading needed - EngineRenderSystem handles it
        // 不需要手动加载纹理 - EngineRenderSystem会处理
    }

    /**
     * Clear all synced entities from tracking.
     * 清除所有已同步实体的跟踪。
     */
    private clearAllFromEngine(): void {
        // Just clear tracking, entity destruction is handled elsewhere
        this.syncedEntities.clear();
    }

    /**
     * Check if initialized.
     * 检查是否已初始化。
     */
    isInitialized(): boolean {
        return this.initialized;
    }

    /**
     * Get synced entity count.
     * 获取已同步实体数量。
     */
    getSyncedCount(): number {
        return this.syncedEntities.size;
    }

    /**
     * Dispose sync service.
     * 释放同步服务。
     */
    dispose(): void {
        // Unsubscribe from all events
        for (const unsub of this.subscriptions) {
            unsub();
        }
        this.subscriptions = [];

        // Clear synced entities
        this.syncedEntities.clear();

        this.initialized = false;
    }
}

export default EditorEngineSync;
