/**
 * 文件功能：聊天室萤火虫特效
 *
 * 使用高亮柔光粒子模拟夜色中的萤火虫，让光点在屏幕中缓慢游走、
 * 呼吸闪烁，适合常驻氛围和安静主题房间。
 */

const FirefliesEffect = (() => {
    class Firefly {
        constructor(w, h) {
            this.w = w;
            this.h = h;
            this.reset();
        }

        /**
         * 重置萤火虫位置与呼吸参数。
         */
        reset() {
            this.x = Math.random() * this.w;
            this.y = Math.random() * this.h;
            this.baseRadius = Math.random() * 3 + 2.4;
            this.alpha = Math.random() * 0.24 + 0.36;
            this.phase = Math.random() * Math.PI * 2;
            this.phaseSpeed = Math.random() * 0.05 + 0.015;
            this.angle = Math.random() * Math.PI * 2;
            this.speed = Math.random() * 0.55 + 0.22;
            this.flutter = Math.random() * Math.PI * 2;
            this.flutterSpeed = Math.random() * 0.18 + 0.08;
            this.trail = [];
        }

        /**
         * 更新萤火虫轨迹。
         */
        update() {
            this.phase += this.phaseSpeed;
            this.flutter += this.flutterSpeed;
            this.trail.push({ x: this.x, y: this.y });
            if (this.trail.length > 7) {
                this.trail.shift();
            }

            this.angle += (Math.random() - 0.5) * 0.08 + Math.sin(this.flutter) * 0.012;
            this.x += Math.cos(this.angle) * this.speed;
            this.y += Math.sin(this.angle) * this.speed;

            if (this.x < -20) this.x = this.w + 20;
            if (this.x > this.w + 20) this.x = -20;
            if (this.y < -20) this.y = this.h + 20;
            if (this.y > this.h + 20) this.y = -20;
        }

        /**
         * 绘制发光萤火虫。
         *
         * @param {CanvasRenderingContext2D} ctx
         */
        draw(ctx) {
            const pulse = 0.38 + (Math.sin(this.phase) + 1) * 0.42;
            const radius = this.baseRadius * pulse;
            const wingSwing = Math.sin(this.flutter) * 1.9;

            this.trail.forEach((point, index) => {
                const alpha = ((index + 1) / this.trail.length) * 0.08;
                ctx.save();
                ctx.fillStyle = `rgba(250, 204, 21, ${alpha})`;
                ctx.shadowColor = "rgba(250, 204, 21, 0.45)";
                ctx.shadowBlur = 6;
                ctx.beginPath();
                ctx.arc(point.x, point.y, Math.max(0.8, radius * 0.55), 0, Math.PI * 2);
                ctx.fill();
                ctx.restore();
            });

            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(this.angle);

            // 先画半透明翅膀，再画虫身和发光尾部，让画面更像“萤火虫”而不是单纯光点。
            ctx.globalAlpha = 0.18 + pulse * 0.08;
            ctx.fillStyle = "#f8fafc";
            ctx.beginPath();
            ctx.ellipse(-radius * 1.15, -radius * 0.45, radius * 1.05, radius * 0.55, wingSwing * 0.05, 0, Math.PI * 2);
            ctx.ellipse(-radius * 0.1, radius * 0.45, radius * 1.05, radius * 0.55, -wingSwing * 0.05, 0, Math.PI * 2);
            ctx.fill();

            ctx.globalAlpha = this.alpha + pulse * 0.3;
            ctx.fillStyle = "#fde047";
            ctx.shadowColor = "rgba(250, 204, 21, 0.85)";
            ctx.shadowBlur = 18 + pulse * 12;
            ctx.beginPath();
            ctx.arc(radius * 0.75, 0, radius, 0, Math.PI * 2);
            ctx.fill();

            ctx.fillStyle = "rgba(51, 65, 85, 0.9)";
            ctx.shadowBlur = 0;
            ctx.beginPath();
            ctx.ellipse(-radius * 0.25, 0, radius * 1.05, Math.max(1.4, radius * 0.5), 0, 0, Math.PI * 2);
            ctx.fill();

            ctx.strokeStyle = "rgba(248, 250, 252, 0.35)";
            ctx.lineWidth = 1;
            ctx.beginPath();
            ctx.moveTo(-radius * 1.1, -radius * 0.2);
            ctx.lineTo(-radius * 1.65, -radius * 0.8);
            ctx.moveTo(-radius * 1.1, radius * 0.2);
            ctx.lineTo(-radius * 1.65, radius * 0.8);
            ctx.stroke();
            ctx.restore();
        }
    }

    /**
     * 启动萤火虫特效。
     *
     * @param {HTMLCanvasElement} canvas
     * @param {Function} onEnd
     */
    function start(canvas, onEnd) {
        const ctx = canvas.getContext("2d");
        const w = canvas.width;
        const h = canvas.height;
        const DURATION = 10500;
        const COUNT = Math.min(52, Math.max(24, Math.floor(w / 34)));
        const fireflies = Array.from({ length: COUNT }, () => new Firefly(w, h));
        const startTime = performance.now();
        let animId = null;
        let finished = false;

        /**
         * 统一结束萤火虫动画，手动取消时只清理不回调。
         *
         * @param {boolean} canceled 是否为手动取消
         */
        function finish(canceled) {
            if (finished) {
                return;
            }

            finished = true;
            if (animId) {
                cancelAnimationFrame(animId);
            }
            ctx.clearRect(0, 0, w, h);
            if (!canceled) {
                onEnd();
            }
        }

        function animate(now) {
            ctx.clearRect(0, 0, w, h);

            fireflies.forEach((firefly) => {
                firefly.update();
                firefly.draw(ctx);
            });

            if (now - startTime < DURATION) {
                animId = requestAnimationFrame(animate);
            } else {
                finish(false);
            }
        }

        animId = requestAnimationFrame(animate);
        return {
            cancel() {
                finish(true);
            },
        };
    }

    return { start };
})();

window.FirefliesEffect = FirefliesEffect;
