#include "game.h"

namespace esp32 {
namespace game {

using namespace esp32::ui;
using namespace esp32::utils;

static uint32_t xorshift32(uint32_t& s){
    uint32_t x = s;
    x ^= x << 13; x ^= x >> 17; x ^= x << 5; s = x; return x;
}

static uint8_t rand7(uint32_t& s){ return (uint8_t)(xorshift32(s) % 7); }

static void setPieceShape(Piece& p){
    // 定义 7 种方块在默认朝向下的 4 个格子偏移
    // 坐标以 (0,0) 为参考，落点左上角附近
    switch (p.type){
        case 0: // I 形: 水平
            p.blocks[0][0] = -1; p.blocks[0][1] = 0;
            p.blocks[1][0] = 0;  p.blocks[1][1] = 0;
            p.blocks[2][0] = 1;  p.blocks[2][1] = 0;
            p.blocks[3][0] = 2;  p.blocks[3][1] = 0; break;
        case 1: // O 方块
            p.blocks[0][0] = 0; p.blocks[0][1] = 0;
            p.blocks[1][0] = 1; p.blocks[1][1] = 0;
            p.blocks[2][0] = 0; p.blocks[2][1] = 1;
            p.blocks[3][0] = 1; p.blocks[3][1] = 1; break;
        case 2: // T
            p.blocks[0][0] = -1; p.blocks[0][1] = 0;
            p.blocks[1][0] = 0;  p.blocks[1][1] = 0;
            p.blocks[2][0] = 1;  p.blocks[2][1] = 0;
            p.blocks[3][0] = 0;  p.blocks[3][1] = 1; break;
        case 3: // L
            p.blocks[0][0] = -1; p.blocks[0][1] = 0;
            p.blocks[1][0] = 0;  p.blocks[1][1] = 0;
            p.blocks[2][0] = 1;  p.blocks[2][1] = 0;
            p.blocks[3][0] = 1;  p.blocks[3][1] = 1; break;
        case 4: // J
            p.blocks[0][0] = -1; p.blocks[0][1] = 0;
            p.blocks[1][0] = 0;  p.blocks[1][1] = 0;
            p.blocks[2][0] = 1;  p.blocks[2][1] = 0;
            p.blocks[3][0] = -1; p.blocks[3][1] = 1; break;
        case 5: // S
            p.blocks[0][0] = 0;  p.blocks[0][1] = 0;
            p.blocks[1][0] = 1;  p.blocks[1][1] = 0;
            p.blocks[2][0] = -1; p.blocks[2][1] = 1;
            p.blocks[3][0] = 0;  p.blocks[3][1] = 1; break;
        case 6: // Z
            p.blocks[0][0] = -1; p.blocks[0][1] = 0;
            p.blocks[1][0] = 0;  p.blocks[1][1] = 0;
            p.blocks[2][0] = 0;  p.blocks[2][1] = 1;
            p.blocks[3][0] = 1;  p.blocks[3][1] = 1; break;
    }
}

static bool collide(const Tetris& g, const Piece& p, int nx, int ny){
    for (int i=0;i<4;++i){
        int cx = nx + p.blocks[i][0];
        int cy = ny + p.blocks[i][1];
        if (cx < 0 || cx >= COLS || cy >= ROWS) return true;
        if (cy >= 0 && g.board[cy][cx] != 0) return true;
    }
    return false;
}

static void spawnPiece(Tetris& g){
    g.current.type = rand7(g.rng);
    g.current.x = COLS/2 - 1;
    g.current.y = -1; // 允许出屏生成
    setPieceShape(g.current);
    // 颜色：从表里取 1..7
    g.current.color = g.colors[1 + (g.current.type % 7)];
    if (collide(g, g.current, g.current.x, g.current.y+1)){
        g.state = State::GameOver;
    }
}

static void lockPiece(Tetris& g){
    for (int i=0;i<4;++i){
        int cx = g.current.x + g.current.blocks[i][0];
        int cy = g.current.y + g.current.blocks[i][1];
        if (cy>=0 && cy<ROWS && cx>=0 && cx<COLS){
            g.board[cy][cx] = 1 + (g.current.type % 7);
        }
    }
}

static int clearLines(Tetris& g){
    int cleared = 0;
    for (int y=ROWS-1; y>=0; --y){
        bool full = true;
        for (int x=0; x<COLS; ++x){ if (g.board[y][x]==0){ full=false; break; } }
        if (full){
            ++cleared;
            for (int yy=y; yy>0; --yy){
                for (int x=0;x<COLS;++x){ g.board[yy][x] = g.board[yy-1][x]; }
            }
            for (int x=0;x<COLS;++x) g.board[0][x]=0;
            ++y; // 重新检查此行
        }
    }
    if (cleared>0){ g.score += cleared * 100; }
    return cleared;
}

void init(Tetris& g){
    // 初始化颜色表
    g.colors[0] = 0; // 未用
    g.colors[1] = WHITE;
    g.colors[2] = rgbTo565(0x00FFFF);   // CYAN
    g.colors[3] = YELLOW;
    g.colors[4] = GREEN;
    g.colors[5] = BLUE;
    g.colors[6] = RED;
    g.colors[7] = rgbTo565(0xFF00FF); // MAGENTA
    reset(g);
}

void reset(Tetris& g){
    for (int y=0;y<ROWS;++y) for (int x=0;x<COLS;++x) g.board[y][x]=0;
    g.state = State::Playing;
    g.score = 0;
    g.dropInterval = 700;
    g.lastDropMs = millis();
    g.rng ^= millis(); if (g.rng==0) g.rng=1;
    spawnPiece(g);
}

void update(Tetris& g, uint32_t nowMs){
    if (g.state != State::Playing) return;
    if (nowMs - g.lastDropMs >= g.dropInterval){
        g.lastDropMs = nowMs;
        if (!collide(g, g.current, g.current.x, g.current.y+1)){
            g.current.y += 1;
        } else {
            lockPiece(g);
            clearLines(g);
            spawnPiece(g);
        }
    }
}

void moveLeft(Tetris& g){
    if (g.state != State::Playing) return;
    if (!collide(g, g.current, g.current.x-1, g.current.y)){
        g.current.x -= 1;
    }
}

void moveRight(Tetris& g){
    if (g.state != State::Playing) return;
    if (!collide(g, g.current, g.current.x+1, g.current.y)){
        g.current.x += 1;
    }
}

void hardDrop(Tetris& g){
    if (g.state != State::Playing) return;
    while (!collide(g, g.current, g.current.x, g.current.y+1)){
        g.current.y += 1;
    }
    lockPiece(g);
    clearLines(g);
    spawnPiece(g);
}

void buildScene(const Tetris& g, DisplayList& out,
                int16_t screenW, int16_t screenH,
                int16_t cell, int16_t originX, int16_t originY){
    // 边框
    out.addFillRect(900, originX-2, originY-2, COLS*cell+4, ROWS*cell+4, WHITE);
    out.addFillRect(901, originX-1, originY-1, COLS*cell+2, ROWS*cell+2, BLACK);

    // 棋盘格子
    for (int y=0; y<ROWS; ++y){
        for (int x=0; x<COLS; ++x){
            uint8_t v = g.board[y][x];
            if (v){
                uint16_t c = g.colors[v % 8];
                out.addFillRect(1000 + y*COLS + x, originX + x*cell, originY + y*cell, cell-1, cell-1, c);
            } else {
                // 画浅网格可选：注释掉减少绘制量
                // out.addFillRect(2000 + y*COLS + x, originX + x*cell, originY + y*cell, cell-1, 1, 0x8410);
            }
        }
    }

    // 当前方块
    if (g.state == State::Playing){
        for (int i=0;i<4;++i){
            int cx = g.current.x + g.current.blocks[i][0];
            int cy = g.current.y + g.current.blocks[i][1];
            if (cy>=0){
                out.addFillRect(3000 + i, originX + cx*cell, originY + cy*cell, cell-1, cell-1, g.current.color);
            }
        }
    }

    // 顶部文字：Score
    char buf[24];
    snprintf(buf, sizeof(buf), "Score: %lu", (unsigned long)g.score);
    out.addText(8000, 4, 4, WHITE, buf);

    if (g.state == State::GameOver){
        out.addText(8001, 8, screenH - 24, YELLOW, "Game Over");
        out.addText(8002, 8, screenH - 14, WHITE, "Left: Home  Right: Retry");
    } else {
        out.addText(8003, 8, screenH - 14, WHITE, "Up: Drop  Left/Right: Move");
    }
}

} // namespace game
} // namespace esp32
