/**
 * 文件功能：聊天室爱心飘落特效
 *
 * 在透明 Canvas 上绘制成组心形，从上方向下飘落并轻微摇摆，
 * 适用于表白、婚礼、节日祝福等氛围场景。
 */

const HeartsEffect = (() => {
    class Heart {
        constructor(w, h) {
            this.w = w;
            this.h = h;
            this.reset(true);
        }

        /**
         * 重置爱心粒子。
         *
         * @param {boolean} initial 是否首次初始化
         */
        reset(initial = false) {
            this.x = Math.random() * this.w;
            this.y = initial ? Math.random() * this.h : -24;
            this.size = Math.random() * 10 + 10;
            this.speedY = Math.random() * 1.5 + 1.1;
            this.swing = Math.random() * Math.PI * 2;
            this.swingSpeed = Math.random() * 0.04 + 0.015;
            this.rotation = (Math.random() - 0.5) * 0.35;
            this.rotationSpeed = (Math.random() - 0.5) * 0.01;
            this.alpha = Math.random() * 0.28 + 0.62;
            this.color = ["#fb7185", "#f43f5e", "#ec4899", "#fda4af"][
                Math.floor(Math.random() * 4)
            ];
        }

        /**
         * 更新爱心位置。
         */
        update() {
            this.swing += this.swingSpeed;
            this.rotation += this.rotationSpeed;
            this.x += Math.sin(this.swing) * 1.1;
            this.y += this.speedY;

            if (this.y > this.h + 28) {
                this.reset(false);
            }
        }

        /**
         * 绘制爱心形状。
         *
         * @param {CanvasRenderingContext2D} ctx
         */
        draw(ctx) {
            const s = this.size;

            ctx.save();
            ctx.translate(this.x, this.y);
            ctx.rotate(this.rotation);
            ctx.scale(s / 16, s / 16);
            ctx.globalAlpha = this.alpha;
            ctx.fillStyle = this.color;
            ctx.shadowColor = "rgba(244, 63, 94, 0.45)";
            ctx.shadowBlur = 10;

            ctx.beginPath();
            ctx.moveTo(0, -4);
            ctx.bezierCurveTo(12, -18, 26, -2, 0, 18);
            ctx.bezierCurveTo(-26, -2, -12, -18, 0, -4);
            ctx.fill();
            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 = 9000;
        const HEART_COUNT = Math.min(48, Math.max(24, Math.floor(w / 34)));
        const hearts = Array.from({ length: HEART_COUNT }, () => new Heart(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);

            hearts.forEach((heart) => {
                heart.update();
                heart.draw(ctx);
            });

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

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

    return { start };
})();

window.HeartsEffect = HeartsEffect;
