#include "Canvas.h"
#include "EngineCore/Game.h"
#include "EngineFrame/Render/RenderManager.h"
Canvas::Canvas(VecSize size)
{
    m_size = size;
    m_renderRect = {0, 0, size.width, size.height};
    m_rect = {0, 0, (float)size.width, (float)size.height};
    m_texture = new Texture();
    m_texture->Init(VecSize(Game::GetInstance().Screen_W, Game::GetInstance().Screen_H));

    Actor::Init();

    glGenFramebuffers(1, &m_fbo);
    glBindFramebuffer(GL_FRAMEBUFFER, m_fbo);
    // 将目标纹理附加到FBO的颜色附着点
    glFramebufferTexture2D(
        GL_FRAMEBUFFER,       // 帧缓冲类型
        GL_COLOR_ATTACHMENT0, // 颜色附着点（可多个，这里用第一个）
        GL_TEXTURE_2D,        // 纹理类型
        m_texture->getID(),   // 目标纹理ID
        0                     // 多级渐远纹理级别
    );
    glBindFramebuffer(GL_FRAMEBUFFER, 0); // 解绑FBO
}

void Canvas::PreRender()
{
    m_rect.x = GetWorldPos().x;
    m_rect.y = GetWorldPos().y;
}

void Canvas::Render()
{
    RenderManager *renderer = Game::GetInstance().GetRenderer();
    SDL_FPoint AnchorPos = {0, 0};
    if (m_dirty)
    {
        glBindFramebuffer(GL_FRAMEBUFFER, m_fbo); // 绑定FBO
        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
        glClear(GL_COLOR_BUFFER_BIT);
        for (auto &info : m_drawQueue)
        {
            renderer->DrawTexture(m_imgMap[info.texture], nullptr, &info.rect, 0.f, &AnchorPos, SDL_FLIP_NONE);
        }
        glBindFramebuffer(GL_FRAMEBUFFER, 0); // 解绑FBO
        m_dirty = false;
    }

    renderer->SetCurrentShaderProgram("flip_y");
    // 混合
    if (this->_BlendMode != NONE)
        Blend();
    renderer->DrawTexture(m_texture, &m_renderRect, &m_rect, 0.f, &AnchorPos, SDL_FLIP_NONE);
    // 还原混合
    if (this->_BlendMode != NONE)
        glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    renderer->SetCurrentShaderProgram("normal");
}

void Canvas::DrawImg(std::string img, int index, Vec2 pos)
{
    m_dirty = true;
    ImgKey key = {img, index};
    DrawInfo info;
    info.rect.x = pos.x;
    info.rect.y = pos.y;
    info.texture = key;

    if (m_imgMap.find(key) == m_imgMap.end())
    {
        RefPtr<Texture> tex = new Texture();
        tex->Init(img, index);
        m_imgMap[key] = tex;
    }

    info.rect.w = m_imgMap[key]->getSize().width;
    info.rect.h = m_imgMap[key]->getSize().height;

    m_drawQueue.push_back(info);
}

void Canvas::DrawImg(std::string img, int index, SDL_FRect rect)
{
    m_dirty = true;
    ImgKey key = {img, index};
    DrawInfo info;
    info.rect = rect;
    info.texture = key;

    if (m_imgMap.find(key) == m_imgMap.end())
    {
        RefPtr<Texture> tex = new Texture();
        tex->Init(img, index);
        m_imgMap[key] = tex;
    }

    m_drawQueue.push_back(info);
}

void Canvas::Clear()
{
    m_drawQueue.clear();
    m_dirty = true;
}

void Canvas::Blend()
{
    switch (this->_BlendMode)
    {
    case LINEARDODGE:
        glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE, GL_ZERO, GL_ONE);
        break;
    }
}
