#include <extra2d/scene/transition_box_scene.h>
#include <extra2d/app/application.h>
#include <extra2d/core/color.h>
#include <extra2d/graphics/core/render_backend.h>
#include <extra2d/platform/iwindow.h>
#include <algorithm>
#include <glm/gtc/matrix_transform.hpp>

namespace extra2d {

/**
 * @brief 构造函数，初始化方块过渡场景
 * @param duration 过渡持续时间（秒）
 * @param inScene 要进入的目标场景
 * @param divisions 方块分割数
 */
TransitionBoxScene::TransitionBoxScene(float duration, Ptr<Scene> inScene,
                                       int divisions)
    : TransitionScene(duration, inScene), divisions_(divisions) {}

/**
 * @brief 创建方块过渡场景的静态工厂方法
 * @param duration 过渡持续时间（秒）
 * @param inScene 要进入的目标场景
 * @param divisions 方块分割数
 * @return 过渡场景智能指针
 */
Ptr<TransitionBoxScene> TransitionBoxScene::create(float duration,
                                                   Ptr<Scene> inScene,
                                                   int divisions) {
  return makePtr<TransitionBoxScene>(duration, inScene, divisions);
}

/**
 * @brief 启动过渡动画
 *
 * 方块过渡不需要特殊的初始化
 */
void TransitionBoxScene::onTransitionStart() {
}

/**
 * @brief 更新过渡进度
 * @param dt 帧间隔时间（秒）
 */
void TransitionBoxScene::updateTransition(float dt) {
  TransitionScene::updateTransition(dt);
}

/**
 * @brief 渲染过渡内容
 * @param renderer 渲染后端引用
 *
 * 先渲染新场景，然后绘制方块遮罩逐渐消失
 */
void TransitionBoxScene::renderContent(RenderBackend &renderer) {
  auto &app = Application::get();
  float windowWidth = static_cast<float>(app.window()->width());
  float windowHeight = static_cast<float>(app.window()->height());

  if (inScene_) {
    inScene_->renderContent(renderer);
  } else if (outScene_) {
    outScene_->renderContent(renderer);
  }

  renderer.setViewport(0, 0, static_cast<int>(windowWidth),
                       static_cast<int>(windowHeight));

  int div = std::max(1, divisions_);
  int total = div * div;
  int visible = std::clamp(static_cast<int>(total * progress_), 0, total);

  float cellW = windowWidth / static_cast<float>(div);
  float cellH = windowHeight / static_cast<float>(div);

  glm::mat4 overlayVP =
      glm::ortho(0.0f, windowWidth, windowHeight, 0.0f, -1.0f, 1.0f);
  renderer.setViewProjection(overlayVP);

  for (int idx = visible; idx < total; ++idx) {
    int x = idx % div;
    int y = idx / div;
    renderer.fillRect(Rect(x * cellW, y * cellH, cellW + 1.0f, cellH + 1.0f),
                      Colors::Black);
  }
}

} // namespace extra2d
