import { dialog } from './dialog.js';
import { outPutInfo, outPutSuccess } from './console-logger.js';

class WatermelonGame {
    constructor() {
        // 定义水果等级和属性
        // 半径单位: px
        // 图片路径相对于 webroot
        this.FRUITS = [
            { level: 0, key: 'grape', label: '葡萄', radius: 20, img: '/images/suika/grape.png' },
            { level: 1, key: 'cherry', label: '樱桃', radius: 30, img: '/images/suika/cherry.png' },
            { level: 2, key: 'orange', label: '橘子', radius: 40, img: '/images/suika/orange.png' },
            { level: 3, key: 'lemon', label: '柠檬', radius: 50, img: '/images/suika/lemon.png' },
            { level: 4, key: 'kiwi', label: '猕猴桃', radius: 60, img: '/images/suika/kiwi.png' },
            { level: 5, key: 'tomato', label: '番茄', radius: 70, img: '/images/suika/tomato.png' },
            { level: 6, key: 'peach', label: '桃子', radius: 80, img: '/images/suika/peach.png' },
            { level: 7, key: 'pineapple', label: '菠萝', radius: 95, img: '/images/suika/pineapple.png' },
            { level: 8, key: 'coconut', label: '椰子', radius: 110, img: '/images/suika/coconut.png' },
            { level: 9, key: 'half-watermelon', label: '半西瓜', radius: 130, img: '/images/suika/half-watermelon.png' },
            { level: 10, key: 'watermelon', label: '大西瓜', radius: 150, img: '/images/suika/watermelon.png' }
        ];

        this.PANEL_WIDTH = 440;
        this.PANEL_HEIGHT = 640;
        
        // 游戏状态
        this.isOpen = false;
        this.overlay = null;
        this.engine = null;
        this.render = null;
        this.runner = null;
        
        // 逻辑控制
        this.currentBody = null; // 当前悬停的水果 Body
        this.nextFruitLevel = 0;
        this.canDrop = true;
        this.isGameOver = false;
        
        // Matter.js 模块引用 (懒加载)
        this.Matter = null;

        this.bindConsoleCommand();
    }

    bindConsoleCommand() {
        window.openWatermelonGame = () => {
            if (this.isOpen) {
                outPutInfo('合成大西瓜已经打开了');
                return;
            }
            this.open();
        };

        outPutInfo('🍉 合成大西瓜 (Matter.js 版)');
        outPutInfo('输入 window.openWatermelonGame() 启动游戏');
    }

    async loadMatterJs() {
        if (window.Matter) {
            this.Matter = window.Matter;
            return;
        }

        return new Promise((resolve, reject) => {
            const script = document.createElement('script');
            script.src = 'https://cdnjs.cloudflare.com/ajax/libs/matter-js/0.19.0/matter.min.js';
            script.onload = () => {
                this.Matter = window.Matter;
                resolve();
            };
            script.onerror = () => {
                outPutInfo('Matter.js 加载失败,请检查网络');
                reject(new Error('Failed to load Matter.js'));
            };
            document.body.appendChild(script);
        });
    }

    async open() {
        if (this.isOpen) return;

        try {
            await this.loadMatterJs();
        } catch (e) {
            console.error(e);
            dialog.alert('加载游戏引擎失败');
            return;
        }

        this.isOpen = true;
        this.createUI();
        this.initGame();
        outPutSuccess('合成大西瓜已启动');
    }

    createUI() {
        const overlay = document.createElement('div');
        overlay.className = 'watermelon-game';
        overlay.innerHTML = `
            <div class="watermelon-game__panel">
                <div class="watermelon-game__header">
                    <h3 class="watermelon-game__title">合成大西瓜</h3>
                    <div class="watermelon-game__actions">
                        <button class="watermelon-game__action" id="wg-restart">重开</button>
                        <button class="watermelon-game__action" id="wg-close" aria-label="关闭">
                            <i class="fa fa-times"></i>
                        </button>
                    </div>
                </div>
                <div class="watermelon-game__content">
                    <aside class="watermelon-game__side watermelon-game__side--left">
                        <h4>合成路径</h4>
                        <div class="watermelon-game__path" id="watermelon-path"></div>
                    </aside>
                    <main class="watermelon-game__center" id="game-container" style="position: relative; padding: 0; overflow: hidden; background: #ffe8cd;">
                        <!-- Canvas will be injected here by Matter.js -->
                        <div id="game-over-mask" style="display:none; position:absolute; inset:0; background:rgba(0,0,0,0.7); color:white; flex-direction:column; justify-content:center; align-items:center; z-index:10;">
                            <h2 style="font-size: 2rem; margin-bottom: 1rem;">游戏结束</h2>
                            <button class="watermelon-game__action" id="wg-retry">再来一局</button>
                        </div>
                    </main>
                    <aside class="watermelon-game__side watermelon-game__side--right">
                        <h4>下一个</h4>
                        <div style="width: 140px; height: 140px; display: flex; justify-content: center; align-items: center; background: white; border-radius: 8px; border: 1px solid #e2e8f0;">
                            <img id="next-fruit-img" src="" style="max-width: 80%; max-height: 80%; object-fit: contain;">
                        </div>
                        <p class="watermelon-game__hint">随机生成前 5 种水果</p>
                    </aside>
                </div>
            </div>
        `;

        document.body.appendChild(overlay);
        this.overlay = overlay;

        // 绑定 UI 事件
        overlay.querySelector('#wg-close').onclick = () => this.close();
        overlay.querySelector('#wg-restart').onclick = () => this.restart();
        overlay.querySelector('#wg-retry').onclick = () => this.restart();

        this.renderPath();
    }

    renderPath() {
        const container = document.getElementById('watermelon-path');
        if (!container) return;
        
        container.innerHTML = '';
        for (let i = 0; i < this.FRUITS.length - 1; i++) {
            const row = document.createElement('div');
            row.className = 'watermelon-game__path-row';
            row.textContent = `${this.FRUITS[i].label} + ${this.FRUITS[i].label} → ${this.FRUITS[i+1].label}`;
            container.appendChild(row);
        }
    }

    initGame() {
        const { Engine, Render, Runner, World, Bodies, Events, Composite, Body } = this.Matter;

        // 1. 创建引擎
        this.engine = Engine.create();

        // 2. 创建渲染器
        const container = document.getElementById('game-container');
        // 获取容器实际大小,因为 CSS 可能会限制它
        const width = 440; // 固定宽度逻辑
        const height = 640;

        this.render = Render.create({
            element: container,
            engine: this.engine,
            options: {
                width: width,
                height: height,
                wireframes: false,
                background: '#ffe8cd', // 暖色背景
                pixelRatio: window.devicePixelRatio 
            }
        });

        // 3. 创建边界墙
        const wallOptions = { 
            isStatic: true, 
            render: { fillStyle: '#ffd180' } 
        };
        const ground = Bodies.rectangle(width / 2, height + 30, width, 60, { isStatic: true, label: 'Ground', render: { fillStyle: '#e6aac3' } }); // 地面略低一点
        const leftWall = Bodies.rectangle(-30, height / 2, 60, height * 2, { isStatic: true, label: 'Wall' });
        const rightWall = Bodies.rectangle(width + 30, height / 2, 60, height * 2, { isStatic: true, label: 'Wall' });
        
        // 警戒线逻辑:我们在 collisionActive 中检测或简单判定最高水果
        // 这里添加一根隐形的线作为参考,或者只是逻辑判断

        World.add(this.engine.world, [ground, leftWall, rightWall]);

        // 4. 运行引擎
        this.runner = Runner.create();
        Runner.run(this.runner, this.engine);
        Render.run(this.render);

        // 5. 事件监听
        Events.on(this.engine, 'collisionStart', (event) => this.handleCollision(event));
        
        // 6. 输入绑定
        const canvas = this.render.canvas;
        
        // 移动事件处理函数
        const moveHandler = (e) => {
            e.preventDefault();
            this.inputMove(e);
        };
        
        // 点击/释放事件处理函数
        const endHandler = (e) => {
            e.preventDefault();
            this.inputClick(e);
        };

        canvas.addEventListener('mousemove', moveHandler);
        canvas.addEventListener('touchmove', moveHandler, { passive: false });
        
        canvas.addEventListener('click', endHandler);
        canvas.addEventListener('touchend', endHandler);

        // 开始第一颗
        this.nextFruitLevel = Math.floor(Math.random() * 5); // 随机 0-4
        this.createNewReadyFruit();
        this.updateNextPreview();
    }

    inputMove(e) {
        if (!this.canDrop || this.isGameOver || !this.currentBody) return;

        const rect = this.render.canvas.getBoundingClientRect();
        // 兼容 touch 和 mouse
        const clientX = e.touches ? e.touches[0].clientX : e.clientX;
        let x = clientX - rect.left;
        
        // 限制范围
        const radius = this.FRUITS[this.currentBody.plugin.level].radius;
        if (x < radius) x = radius;
        if (x > this.PANEL_WIDTH - radius) x = this.PANEL_WIDTH - radius;

        this.Matter.Body.setPosition(this.currentBody, {
            x: x,
            y: this.currentBody.position.y
        });
    }

    inputClick(e) {
        if (!this.canDrop || this.isGameOver || !this.currentBody) return;
        this.canDrop = false;

        const body = this.currentBody;
        this.Matter.Body.setStatic(body, false); // 让它掉落
        this.currentBody = null;

        // 1秒后生成下一个
        setTimeout(() => {
            if (!this.isGameOver) {
                this.createNewReadyFruit();
                this.canDrop = true;
            }
        }, 1000);
    }

    // 创建顶部待命的水果
    createNewReadyFruit() {
        const level = this.nextFruitLevel;
        
        // 随机生成下一个 (0-4级: 葡萄到猕猴桃)
        this.nextFruitLevel = Math.floor(Math.random() * 5);
        this.updateNextPreview();

        const fruitConf = this.FRUITS[level];
        const x = this.PANEL_WIDTH / 2;
        const y = 50; // 顶部位置

        const body = this.createFruitBody(x, y, level, true);
        
        this.Matter.Composite.add(this.engine.world, body);
        this.currentBody = body;
    }

    // 创建水果实体(通用方法)
    createFruitBody(x, y, level, isStatic = false) {
        const fruitConf = this.FRUITS[level];
        const body = this.Matter.Bodies.circle(x, y, fruitConf.radius, {
            isStatic: isStatic,
            label: 'Fruit',
            restitution: 0.2, // 弹性
            friction: 0.1,    // 摩擦
            render: {
                sprite: {
                    texture: fruitConf.img
                }
            }
        });
        
        // 附加自定义属性
        body.plugin = { level: level };

        // 异步修正 Scale
        const img = new Image();
        img.src = fruitConf.img;
        img.onload = () => {
            // 计算缩放比例:根据半径算出直径,再除以图片原始宽度
            const scale = (fruitConf.radius * 2) / img.width;
            body.render.sprite.xScale = scale;
            body.render.sprite.yScale = scale;
        };

        return body;
    }

    updateNextPreview() {
        const img = document.getElementById('next-fruit-img');
        if (img) {
            img.src = this.FRUITS[this.nextFruitLevel].img;
        }
    }

    handleCollision(event) {
        if (this.isGameOver) return;

        const { pairs } = event;
        const { Composite, Body, Vector, World } = this.Matter;

        // 找出需要合成的对
        // 注意:collisionStart 可能在一步包含多个碰撞
        // 我们需要标记已经处理过的 body 防止重复
        const processedBodies = new Set();
        const merges = [];

        for (let i = 0; i < pairs.length; i++) {
            const pair = pairs[i];
            const bodyA = pair.bodyA;
            const bodyB = pair.bodyB;

            if (bodyA.label === 'Fruit' && bodyB.label === 'Fruit') {
                const levelA = bodyA.plugin.level;
                const levelB = bodyB.plugin.level;

                if (levelA === levelB && levelA < this.FRUITS.length - 1) {
                    if (processedBodies.has(bodyA.id) || processedBodies.has(bodyB.id)) continue;

                    processedBodies.add(bodyA.id);
                    processedBodies.add(bodyB.id);

                    merges.push({ bodyA, bodyB, level: levelA });
                }
            }
        }

        // 执行合成
        for (const merge of merges) {
            const { bodyA, bodyB, level } = merge;
            
            // 移除旧的
            Composite.remove(this.engine.world, [bodyA, bodyB]);
            
            // 计算新位置(中心点)
            const x = (bodyA.position.x + bodyB.position.x) / 2;
            const y = (bodyA.position.y + bodyB.position.y) / 2;
            
            const newLevel = level + 1;
            const newBody = this.createFruitBody(x, y, newLevel, false);

            Composite.add(this.engine.world, newBody);

            // 检查胜利
            if (newLevel === this.FRUITS.length - 1) {
                 outPutSuccess('太强了!合成大西瓜!');
            }
        }
    }

    restart() {
        if (!this.engine) return;
        
        const { Composite } = this.Matter;
        Composite.clear(this.engine.world, false); // clear all bodies (except static walls if handled carefully, but clear removes everything usually)
        
        // 因为 clear 清除了 walls,需要重建
        this.engine.events = {}; // 清除所有事件监听? 不,clear 不清除事件。
        
        // 简单暴力:停止一切,重新 initGame
        // 但为了性能,最好只是清空实体
        
        // 更好的 restart:
        // 1. 找出所有 label='Fruit' 的 body 并移除
        const bodies = Composite.allBodies(this.engine.world);
        const fruits = bodies.filter(b => b.label === 'Fruit');
        Composite.remove(this.engine.world, fruits);
        
        this.cleanGameOver();
        this.nextFruitLevel = 0;
        this.canDrop = true;
        this.createNewReadyFruit();
        this.updateNextPreview();
    }
    
    cleanGameOver() {
        this.isGameOver = false;
        const mask = document.getElementById('game-over-mask');
        if (mask) mask.style.display = 'none';
    }

    close() {
        if (!this.isOpen) return;

        // 停止引擎
        if (this.runner) {
            this.Matter.Runner.stop(this.runner);
        }
        if (this.render) {
            this.Matter.Render.stop(this.render);
            if (this.render.canvas) {
                this.render.canvas.remove();
            }
        }
        
        if (this.overlay) {
            this.overlay.remove();
            this.overlay = null;
        }

        this.isOpen = false;
        this.engine = null;
        this.render = null;
    }
}

export const watermelonGame = new WatermelonGame();
评论加载中...