#include <extra2d/graphics/batch/sprite_batch.h>
#include <extra2d/utils/logger.h>

#include <cmath>
#include <cstring>

namespace extra2d {

// ============================================================================
// TrigLookup 实现 - 三角函数查表
// ============================================================================
TrigLookup::TrigLookup() {
    constexpr float PI = 3.14159265359f;
    constexpr float DEG2RAD = PI / 180.0f;
    
    for (int i = 0; i < TABLE_SIZE; ++i) {
        float angle = static_cast<float>(i) * (360.0f / TABLE_SIZE) * DEG2RAD;
        sinTable_[i] = std::sin(angle);
        cosTable_[i] = std::cos(angle);
    }
}

float TrigLookup::sin(int angle) const {
    // 规范化角度到 0-360
    angle = ((angle % 360) + 360) % 360;
    return sinTable_[angle * 4];
}

float TrigLookup::cos(int angle) const {
    // 规范化角度到 0-360
    angle = ((angle % 360) + 360) % 360;
    return cosTable_[angle * 4];
}

float TrigLookup::sinRad(float rad) const {
    constexpr float RAD2DEG = 180.0f / 3.14159265359f;
    int angle = static_cast<int>(rad * RAD2DEG);
    return sin(angle);
}

float TrigLookup::cosRad(float rad) const {
    constexpr float RAD2DEG = 180.0f / 3.14159265359f;
    int angle = static_cast<int>(rad * RAD2DEG);
    return cos(angle);
}

// ============================================================================
// SpriteBatch 实现
// ============================================================================
SpriteBatch::SpriteBatch() 
    : spriteCount_(0)
    , vpDirty_(true) {
    // 预分配顶点缓冲区
    vertices_.reserve(MAX_VERTICES);
    indices_.reserve(MAX_INDICES);
    
    // 生成静态索引缓冲区
    generateIndices();
}

void SpriteBatch::generateIndices() {
    indices_.clear();
    for (size_t i = 0; i < MAX_SPRITES; ++i) {
        uint16_t base = static_cast<uint16_t>(i * 4);
        // 两个三角形: (0,1,2) 和 (0,2,3)
        indices_.push_back(base + 0);
        indices_.push_back(base + 1);
        indices_.push_back(base + 2);
        indices_.push_back(base + 0);
        indices_.push_back(base + 2);
        indices_.push_back(base + 3);
    }
}

void SpriteBatch::begin(const glm::mat4& viewProjection) {
    viewProjection_ = viewProjection;
    vpDirty_ = true;
    spriteCount_ = 0;
    vertices_.clear();
}

void SpriteBatch::end() {
    // 批次结束，数据已准备好供后端使用
}

void SpriteBatch::draw(const SpriteData& sprite) {
    if (spriteCount_ >= MAX_SPRITES) {
        // 缓冲区已满，需要刷新
        flush();
    }
    
    generateVertices(sprite, spriteCount_ * VERTICES_PER_SPRITE);
    spriteCount_++;
}

void SpriteBatch::drawBatch(const std::vector<SpriteData>& sprites) {
    size_t index = 0;
    while (index < sprites.size()) {
        // 计算剩余空间
        size_t remainingSpace = MAX_SPRITES - spriteCount_;
        size_t batchSize = std::min(remainingSpace, sprites.size() - index);
        
        // 批量生成顶点
        for (size_t i = 0; i < batchSize; ++i) {
            generateVertices(sprites[index + i], spriteCount_ * VERTICES_PER_SPRITE);
            spriteCount_++;
        }
        
        index += batchSize;
        
        // 如果缓冲区已满，需要刷新（由后端处理）
        if (spriteCount_ >= MAX_SPRITES && index < sprites.size()) {
            // 通知后端刷新，然后继续
            // 注意：这里只是准备数据，实际 GPU 提交由后端决定
            break;
        }
    }
}

void SpriteBatch::drawImmediate(const SpriteData& sprite) {
    // 立即绘制模式：清空当前批次，只绘制这一个精灵
    clear();
    draw(sprite);
}

void SpriteBatch::generateVertices(const SpriteData& sprite, size_t vertexOffset) {
    // 确保顶点缓冲区足够
    if (vertices_.size() < vertexOffset + VERTICES_PER_SPRITE) {
        vertices_.resize(vertexOffset + VERTICES_PER_SPRITE);
    }
    
    // 计算旋转（使用查表）
    float c = 1.0f;
    float s = 0.0f;
    if (sprite.rotation != 0.0f) {
        c = trigLookup_.cosRad(sprite.rotation);
        s = trigLookup_.sinRad(sprite.rotation);
    }
    
    // 计算精灵的四个角（相对于中心点）
    float halfWidth = sprite.size.x * 0.5f;
    float halfHeight = sprite.size.y * 0.5f;
    
    // 考虑 pivot 偏移
    float pivotOffsetX = (sprite.pivot.x - 0.5f) * sprite.size.x;
    float pivotOffsetY = (sprite.pivot.y - 0.5f) * sprite.size.y;
    
    // 四个角的本地坐标
    Vec2 localCorners[4] = {
        Vec2(-halfWidth - pivotOffsetX, -halfHeight - pivotOffsetY), // 左下
        Vec2( halfWidth - pivotOffsetX, -halfHeight - pivotOffsetY), // 右下
        Vec2( halfWidth - pivotOffsetX,  halfHeight - pivotOffsetY), // 右上
        Vec2(-halfWidth - pivotOffsetX,  halfHeight - pivotOffsetY)  // 左上
    };
    
    // 应用旋转和平移
    Vec2 worldPos = sprite.position;
    
    for (int i = 0; i < 4; ++i) {
        Vec2 rotated;
        if (sprite.rotation != 0.0f) {
            rotated.x = localCorners[i].x * c - localCorners[i].y * s;
            rotated.y = localCorners[i].x * s + localCorners[i].y * c;
        } else {
            rotated = localCorners[i];
        }
        
        vertices_[vertexOffset + i].position = worldPos + rotated;
    }
    
    // 设置纹理坐标
    // uvRect.origin = (u0, v0) - 左下
    // uvRect.size = (width, height) - 从左上到右下的尺寸
    float u0 = sprite.uvRect.origin.x;
    float v0 = sprite.uvRect.origin.y;
    float u1 = u0 + sprite.uvRect.size.width;
    float v1 = v0 + sprite.uvRect.size.height;
    
    // 顶点顺序: 左下, 右下, 右上, 左上
    // 注意: 在 gl_font_atlas 中 v0 > v1 (因为翻转了V坐标)
    // 所以 v0 对应底部，v1 对应顶部
    vertices_[vertexOffset + 0].texCoord = Vec2(u0, v0); // 左下
    vertices_[vertexOffset + 1].texCoord = Vec2(u1, v0); // 右下
    vertices_[vertexOffset + 2].texCoord = Vec2(u1, v1); // 右上
    vertices_[vertexOffset + 3].texCoord = Vec2(u0, v1); // 左上
    
    // 设置颜色
    for (int i = 0; i < 4; ++i) {
        vertices_[vertexOffset + i].color = sprite.color;
    }
}

void SpriteBatch::flush() {
    // 标记需要刷新 - 实际刷新由后端处理
    // 这里只是重置计数器，让后端知道需要提交当前批次
    spriteCount_ = 0;
    vertices_.clear();
}

void SpriteBatch::clear() {
    spriteCount_ = 0;
    vertices_.clear();
}

} // namespace extra2d
