/**
 * @file main.cpp
 * @brief Extra2D 场景图测试示例
 */

#include <extra2d/extra2d.h>
#include <iostream>

using namespace extra2d;

/**
 * @brief 基础场景类，演示场景图功能
 */
class BasicScene : public Scene {
public:
  /**
   * @brief 场景进入时初始化场景图
   */
  void onEnter() override {
    float width = getWidth();
    float height = getHeight();

    auto root = makeShared<Node>();
    root->setName("Root");
    root->setPos(width / 2, height / 2);
    addChild(root);

    auto parent1 = makeShared<Node>();
    parent1->setName("Parent1");
    parent1->setPos(-200, 0);
    root->addChild(parent1);

    auto rect1 = ShapeNode::createFilledRect(Rect(-50, -50, 100, 100),
                                             Color(1.0f, 0.4f, 0.4f, 1.0f));
    rect1->setName("RedRect");
    parent1->addChild(rect1);

    auto child1 = makeShared<Node>();
    child1->setName("Child1");
    child1->setPos(80, 0);
    child1->setRotation(45);
    child1->setScale(0.5f);
    parent1->addChild(child1);

    auto smallRect = ShapeNode::createFilledRect(Rect(-30, -30, 60, 60),
                                                 Color(1.0f, 0.8f, 0.4f, 1.0f));
    smallRect->setName("OrangeRect");
    child1->addChild(smallRect);

    auto parent2 = makeShared<Node>();
    parent2->setName("Parent2");
    parent2->setPos(200, 0);
    root->addChild(parent2);

    auto circle1 = ShapeNode::createFilledCircle(Vec2(0, 0), 60,
                                                 Color(0.4f, 0.4f, 1.0f, 1.0f));
    circle1->setName("BlueCircle");
    parent2->addChild(circle1);

    auto child2 = makeShared<Node>();
    child2->setName("Child2");
    child2->setPos(0, 100);
    parent2->addChild(child2);

    auto triangle = ShapeNode::createFilledTriangle(
        Vec2(0, -40), Vec2(-35, 30), Vec2(35, 30),
        Color(0.4f, 1.0f, 0.4f, 1.0f));
    triangle->setName("GreenTriangle");
    child2->addChild(triangle);

    auto line = ShapeNode::createLine(Vec2(-300, -200), Vec2(300, -200),
                                      Color(1.0f, 1.0f, 1.0f, 1.0f), 2.0f);
    line->setName("BottomLine");
    root->addChild(line);

    auto polygon = ShapeNode::createFilledPolygon(
        {Vec2(0, -50), Vec2(50, 0), Vec2(30, 50), Vec2(-30, 50), Vec2(-50, 0)},
        Color(1.0f, 0.4f, 1.0f, 1.0f));
    polygon->setName("PurplePolygon");
    polygon->setPos(0, -150);
    root->addChild(polygon);
  }

  /**
   * @brief 场景退出时清理资源
   */
  void onExit() override { clearChildren(); }

  /**
   * @brief 自定义渲染逻辑
   * @param renderer 渲染后端
   */
  void onRender(RenderBackend &renderer) override { Scene::onRender(renderer); }
};

int main(int argc, char *argv[]) {
  (void)argc;
  (void)argv;

  std::cout << "Extra2D Scene Graph Demo - Starting..." << std::endl;

  Application &app = Application::get();

  app.use<WindowModule>([](auto &cfg) {
    cfg.w = 1280;
    cfg.h = 720;
    cfg.priority = 0;
    cfg.backend = "glfw";
  });

  app.use<RenderModule>([](auto &cfg) {
    cfg.priority = 10;
    cfg.backend = "opengl";
  });

  app.use<InputModule>([](auto &cfg) { cfg.priority = 20; });

  std::cout << "Initializing application..." << std::endl;
  if (!app.init()) {
    std::cerr << "Failed to initialize application!" << std::endl;
    return -1;
  }

  std::cout << "Application initialized successfully!" << std::endl;

  auto *win = app.window();
  if (win) {
    std::cout << "Window: " << win->width() << "x" << win->height()
              << std::endl;
  }

  auto eventService = ServiceLocator::instance().getService<IEventService>();
  if (eventService) {
    eventService->addListener(EventType::KeyPressed, [](Event &e) {
      auto &keyEvent = std::get<KeyEvent>(e.data);
      if (keyEvent.keyCode == static_cast<int>(Key::Escape)) {
        e.handled = true;
        Application::get().quit();
      }
    });

    eventService->addListener(EventType::MouseButtonPressed, [](Event &e) {
      auto &mouseEvent = std::get<MouseButtonEvent>(e.data);
      std::cout << "[Click] Button " << mouseEvent.button << " at ("
                << mouseEvent.position.x << ", " << mouseEvent.position.y << ")"
                << std::endl;
    });
  }

  auto scene = makeShared<BasicScene>();
  scene->setBackgroundColor(Color(0.12f, 0.12f, 0.16f, 1.0f));
  if (win) {
    scene->setViewportSize(static_cast<float>(win->width()),
                           static_cast<float>(win->height()));
  }

  auto cameraService = ServiceLocator::instance().getService<ICameraService>();
  if (cameraService && win) {
    ViewportConfig vpConfig;
    vpConfig.logicWidth = static_cast<float>(win->width());
    vpConfig.logicHeight = static_cast<float>(win->height());
    vpConfig.mode = ViewportMode::AspectRatio;
    cameraService->setViewportConfig(vpConfig);
    cameraService->updateViewport(win->width(), win->height());
    cameraService->applyViewportAdapter();
  }

  app.enterScene(scene);

  std::cout << "\nControls:" << std::endl;
  std::cout << "  ESC - Exit" << std::endl;
  std::cout << "  Mouse Click - Print position" << std::endl;
  std::cout << "\nRunning main loop...\n" << std::endl;

  app.run();

  std::cout << "Shutting down..." << std::endl;
  app.shutdown();

  std::cout << "Goodbye!" << std::endl;
  return 0;
}
