#include <extra2d/scene/transition_slide_scene.h>
#include <extra2d/graphics/camera/camera.h>
#include <extra2d/graphics/core/render_backend.h>
#include <algorithm>

namespace extra2d {

/**
 * @brief 构造函数，初始化滑动过渡场景
 * @param duration 过渡持续时间（秒）
 * @param inScene 要进入的目标场景
 * @param direction 滑动方向
 */
TransitionSlideScene::TransitionSlideScene(float duration, Ptr<Scene> inScene,
                                           TransitionDirection direction)
    : TransitionScene(duration, inScene), direction_(direction) {}

/**
 * @brief 创建滑动过渡场景的静态工厂方法
 * @param duration 过渡持续时间（秒）
 * @param inScene 要进入的目标场景
 * @param direction 滑动方向
 * @return 过渡场景智能指针
 */
Ptr<TransitionSlideScene> TransitionSlideScene::create(
    float duration, Ptr<Scene> inScene, TransitionDirection direction) {
  return makePtr<TransitionSlideScene>(duration, inScene, direction);
}

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

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

/**
 * @brief 渲染过渡内容
 * @param renderer 渲染后端引用
 *
 * 根据进度控制新旧场景的滑动位置
 */
void TransitionSlideScene::renderContent(RenderBackend &renderer) {
  float screenWidth = 800.0f;
  float screenHeight = 600.0f;

  if (outScene_) {
    Size viewportSize = outScene_->getViewportSize();
    if (viewportSize.width > 0 && viewportSize.height > 0) {
      screenWidth = viewportSize.width;
      screenHeight = viewportSize.height;
    }
  } else if (inScene_) {
    Size viewportSize = inScene_->getViewportSize();
    if (viewportSize.width > 0 && viewportSize.height > 0) {
      screenWidth = viewportSize.width;
      screenHeight = viewportSize.height;
    }
  }

  float easeProgress = progress_ < 0.5f ? 2.0f * progress_ * progress_
                                        : -1.0f + (4.0f - 2.0f * progress_) * progress_;

  if (outScene_) {
    float offsetX = 0.0f;
    float offsetY = 0.0f;

    switch (direction_) {
    case TransitionDirection::Left:
      offsetX = -screenWidth * easeProgress;
      break;
    case TransitionDirection::Right:
      offsetX = screenWidth * easeProgress;
      break;
    case TransitionDirection::Up:
      offsetY = -screenHeight * easeProgress;
      break;
    case TransitionDirection::Down:
      offsetY = screenHeight * easeProgress;
      break;
    }

    Camera *camera = outScene_->getActiveCamera();
    Vec2 originalPos = camera ? camera->getPosition() : Vec2::Zero();

    if (camera) {
      camera->setPos(originalPos.x + offsetX, originalPos.y + offsetY);
    }

    outScene_->renderContent(renderer);

    if (camera) {
      camera->setPos(originalPos);
    }
  }

  if (inScene_) {
    float offsetX = 0.0f;
    float offsetY = 0.0f;

    switch (direction_) {
    case TransitionDirection::Left:
      offsetX = screenWidth * (1.0f - easeProgress);
      break;
    case TransitionDirection::Right:
      offsetX = -screenWidth * (1.0f - easeProgress);
      break;
    case TransitionDirection::Up:
      offsetY = screenHeight * (1.0f - easeProgress);
      break;
    case TransitionDirection::Down:
      offsetY = -screenHeight * (1.0f - easeProgress);
      break;
    }

    Camera *camera = inScene_->getActiveCamera();
    Vec2 originalPos = camera ? camera->getPosition() : Vec2::Zero();

    if (camera) {
      camera->setPos(originalPos.x + offsetX, originalPos.y + offsetY);
    }

    inScene_->renderContent(renderer);

    if (camera) {
      camera->setPos(originalPos);
    }
  }

}

} // namespace extra2d
