/**
 * UI Text Render System
 * UI 文本渲染系统
 *
 * Renders UITextComponent entities by generating text textures
 * and submitting them to the shared UIRenderCollector.
 * 通过生成文本纹理并提交到共享的 UIRenderCollector 来渲染 UITextComponent 实体。
 */

import { EntitySystem, Matcher, Entity, ECSSystem } from '@esengine/ecs-framework';
import { UITransformComponent } from '../../components/UITransformComponent';
import { UITextComponent } from '../../components/UITextComponent';
import { getUIRenderCollector, registerCacheInvalidationCallback, unregisterCacheInvalidationCallback } from './UIRenderCollector';

/**
 * Text texture cache entry
 * 文本纹理缓存条目
 */
interface TextTextureCache {
    textureId: number;
    text: string;
    fontSize: number;
    fontFamily: string;
    fontWeight: string | number;
    italic: boolean;
    color: number;
    alpha: number;
    align: string;
    verticalAlign: string;
    lineHeight: number;
    width: number;
    height: number;
    dataUrl: string;
}

/**
 * UI Text Render System
 * UI 文本渲染系统
 *
 * Handles rendering of text components by:
 * 1. Generating text textures using Canvas 2D
 * 2. Caching textures to avoid regeneration every frame
 * 3. Submitting texture render primitives to the collector
 *
 * 处理文本组件的渲染：
 * 1. 使用 Canvas 2D 生成文本纹理
 * 2. 缓存纹理以避免每帧重新生成
 * 3. 向收集器提交纹理渲染原语
 */
@ECSSystem('UITextRender', { updateOrder: 120 })
export class UITextRenderSystem extends EntitySystem {
    private textCanvas: HTMLCanvasElement | null = null;
    private textCtx: CanvasRenderingContext2D | null = null;
    private textTextureCache: Map<number, TextTextureCache> = new Map();
    private nextTextureId = 90000;
    private onTextureCreated: ((id: number, dataUrl: string) => void) | null = null;
    private cacheInvalidationBound: () => void;

    constructor() {
        super(Matcher.empty().all(UITransformComponent, UITextComponent));
        // Bind the method for cache invalidation callback
        this.cacheInvalidationBound = this.clearTextCache.bind(this);
    }

    /**
     * Called when system is added to scene
     * 系统添加到场景时调用
     */
    public override initialize(): void {
        super.initialize();
        // Register for cache invalidation events
        registerCacheInvalidationCallback(this.cacheInvalidationBound);
    }

    /**
     * Called when system is destroyed
     * 系统销毁时调用
     */
    protected override onDestroy(): void {
        super.onDestroy();
        // Unregister cache invalidation callback
        unregisterCacheInvalidationCallback(this.cacheInvalidationBound);
    }

    /**
     * Set callback for when a new text texture is created
     * 设置创建新文本纹理时的回调
     */
    setTextureCallback(callback: (id: number, dataUrl: string) => void): void {
        this.onTextureCreated = callback;
    }

    protected process(entities: readonly Entity[]): void {
        const collector = getUIRenderCollector();

        for (const entity of entities) {
            const transform = entity.getComponent(UITransformComponent)!;
            const text = entity.getComponent(UITextComponent)!;

            if (!transform.visible || !text.text) continue;

            const x = transform.worldX ?? transform.x;
            const y = transform.worldY ?? transform.y;
            const width = (transform.computedWidth ?? transform.width) * transform.scaleX;
            const height = (transform.computedHeight ?? transform.height) * transform.scaleY;
            const alpha = transform.worldAlpha ?? transform.alpha;
            const baseOrder = 100 + transform.zIndex;

            // Generate or retrieve cached texture
            // 生成或获取缓存的纹理
            const textureId = this.getOrCreateTextTexture(
                entity.id, text, Math.ceil(width), Math.ceil(height)
            );

            if (textureId === null) continue;

            // Use top-left position with origin at (0, 0)
            // 使用左上角位置，原点在 (0, 0)
            collector.addRect(
                x, y,
                width, height,
                0xFFFFFF,  // White tint (color is baked into texture)
                alpha,
                baseOrder + 1,  // Text renders above background
                {
                    rotation: transform.rotation,
                    pivotX: 0,
                    pivotY: 0,
                    textureId
                }
            );
        }
    }

    /**
     * Get or create text texture
     * 获取或创建文本纹理
     */
    private getOrCreateTextTexture(
        entityId: number,
        text: UITextComponent,
        width: number,
        height: number
    ): number | null {
        const canvasData = this.getTextCanvas();
        if (!canvasData) return null;

        const { canvas, ctx } = canvasData;

        const cached = this.textTextureCache.get(entityId);

        // Check if we need to regenerate the texture
        // 检查是否需要重新生成纹理
        const needsUpdate = !cached ||
            cached.text !== text.text ||
            cached.fontSize !== text.fontSize ||
            cached.fontFamily !== text.fontFamily ||
            cached.fontWeight !== text.fontWeight ||
            cached.italic !== text.italic ||
            cached.color !== text.color ||
            cached.alpha !== text.alpha ||
            cached.align !== text.align ||
            cached.verticalAlign !== text.verticalAlign ||
            cached.lineHeight !== text.lineHeight ||
            cached.width !== width ||
            cached.height !== height;

        if (needsUpdate) {
            const canvasWidth = Math.max(1, width);
            const canvasHeight = Math.max(1, height);

            canvas.width = canvasWidth;
            canvas.height = canvasHeight;

            ctx.clearRect(0, 0, canvasWidth, canvasHeight);

            ctx.font = text.getCSSFont();
            ctx.fillStyle = text.getCSSColor();
            ctx.textBaseline = 'top';

            // Handle horizontal alignment
            // 处理水平对齐
            let textX = 0;
            if (text.align === 'center') {
                ctx.textAlign = 'center';
                textX = canvasWidth / 2;
            } else if (text.align === 'right') {
                ctx.textAlign = 'right';
                textX = canvasWidth;
            } else {
                ctx.textAlign = 'left';
                textX = 0;
            }

            // Handle vertical alignment
            // 处理垂直对齐
            const textHeight = text.fontSize * text.lineHeight;
            let textY = 0;

            if (text.verticalAlign === 'middle') {
                textY = (canvasHeight - textHeight) / 2;
            } else if (text.verticalAlign === 'bottom') {
                textY = canvasHeight - textHeight;
            }

            // Draw text (with or without word wrap)
            // 绘制文本（带或不带自动换行）
            if (text.wordWrap) {
                this.drawWrappedText(ctx, text.text, textX, textY, canvasWidth, text.fontSize * text.lineHeight);
            } else {
                ctx.fillText(text.text, textX, textY);
            }

            // Get or create texture ID
            // 获取或创建纹理 ID
            const textureId = cached?.textureId ?? this.nextTextureId++;

            const dataUrl = canvas.toDataURL('image/png');

            // Notify callback of new texture
            // 通知回调新纹理
            if (this.onTextureCreated) {
                this.onTextureCreated(textureId, dataUrl);
            }

            // Update cache
            // 更新缓存
            this.textTextureCache.set(entityId, {
                textureId,
                text: text.text,
                fontSize: text.fontSize,
                fontFamily: text.fontFamily,
                fontWeight: text.fontWeight,
                italic: text.italic,
                color: text.color,
                alpha: text.alpha,
                align: text.align,
                verticalAlign: text.verticalAlign,
                lineHeight: text.lineHeight,
                width,
                height,
                dataUrl
            });
        }

        return this.textTextureCache.get(entityId)?.textureId ?? null;
    }

    /**
     * Get or create text canvas
     * 获取或创建文本画布
     */
    private getTextCanvas(): { canvas: HTMLCanvasElement; ctx: CanvasRenderingContext2D } | null {
        if (!this.textCanvas) {
            this.textCanvas = document.createElement('canvas');
            this.textCtx = this.textCanvas.getContext('2d');
        }
        if (!this.textCtx) return null;
        return { canvas: this.textCanvas, ctx: this.textCtx };
    }

    /**
     * Draw text with word wrapping
     * 绘制带自动换行的文本
     */
    private drawWrappedText(
        ctx: CanvasRenderingContext2D,
        text: string,
        x: number,
        y: number,
        maxWidth: number,
        lineHeight: number
    ): void {
        const words = text.split(' ');
        let line = '';
        let currentY = y;

        for (const word of words) {
            const testLine = line + word + ' ';
            const metrics = ctx.measureText(testLine);

            if (metrics.width > maxWidth && line !== '') {
                ctx.fillText(line.trim(), x, currentY);
                line = word + ' ';
                currentY += lineHeight;
            } else {
                line = testLine;
            }
        }

        if (line.trim()) {
            ctx.fillText(line.trim(), x, currentY);
        }
    }

    /**
     * Clear text texture cache
     * 清除文本纹理缓存
     */
    clearTextCache(): void {
        this.textTextureCache.clear();
    }

    /**
     * Clear cache for a specific entity
     * 清除特定实体的缓存
     */
    clearEntityTextCache(entityId: number): void {
        this.textTextureCache.delete(entityId);
    }

    /**
     * Dispose resources
     * 释放资源
     */
    dispose(): void {
        this.textCanvas = null;
        this.textCtx = null;
        this.textTextureCache.clear();
        this.onTextureCreated = null;
    }
}
