#include "SDL_log.h"
#include "frostbite2D/2d/sprite.h"
#include "frostbite2D/base/RefPtr.h"
#include <SDL2/SDL.h>
#include <exception>
#include <stdexcept>
#include <string>
#include <vector>

#include <frostbite2D/2d/text_sprite.h>
#include <frostbite2D/audio/audio_system.h>
#include <frostbite2D/core/application.h>
#include <frostbite2D/core/task_system.h>
#include <frostbite2D/graphics/font_manager.h>
#include <frostbite2D/resource/asset.h>
#include <frostbite2D/resource/npk_archive.h>
#include <frostbite2D/resource/pvf_archive.h>
#include <frostbite2D/resource/sound_pack_archive.h>
#include <frostbite2D/scene/scene.h>
#include <frostbite2D/scene/scene_manager.h>

using namespace frostbite2D;

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

  AppConfig config = AppConfig::createDefault();
  config.appName = "Frostbite2D Test App";
  config.appVersion = "1.0.0";
  config.windowConfig.width = 1280;
  config.windowConfig.height = 720;
  config.windowConfig.title = "Frostbite2D - Async Init Demo";

  Application &app = Application::get();
  if (!app.init(config)) {
    SDL_LogError(SDL_LOG_CATEGORY_APPLICATION,
                 "Failed to initialize application!");
    return -1;
  }

  app.run([]() {
    auto &fontManager = FontManager::get();
    fontManager.init();
    fontManager.registerFont("default", "assets/Fonts/VonwaonBitmap-12px.ttf",
                             12);

    auto &audioSystem = AudioSystem::get();
    audioSystem.init();
    audioSystem.setMasterVolume(1.0f);
    audioSystem.setSoundVolume(0.8f);
    audioSystem.setMusicVolume(0.6f);

    SDL_Log("游戏启动");

    auto LoadingScene = MakePtr<Scene>();
    SceneManager::get().PushScene(LoadingScene);

    auto Background = Sprite::createFromFile("assets/ImagePacks2/Loading0.jpg");
    Background->SetSize(1280, 720);
    LoadingScene->AddChild(Background);

    auto BackgroundBar =
        Sprite::createFromFile("assets/ImagePacks2/Loading1.png");
    BackgroundBar->SetPosition(0, 686);
    LoadingScene->AddChild(BackgroundBar);

    auto LoadCircleSp =
        Sprite::createFromFile("assets/ImagePacks2/Loading2.png");
    LoadCircleSp->SetAnchor(Vec2(0.5f, 0.5f));
    LoadCircleSp->SetPosition(1280 / 2.0f, 686 - 60);
    LoadCircleSp->SetBlendMode(BlendMode::Additive);
    LoadCircleSp->AddUpdateListener([](Actor &self, float dt) {
      auto rotation = self.GetRotation();
      self.SetRotation(rotation + 180.0f * dt);
    });
    LoadingScene->AddChild(LoadCircleSp);

    TaskSystem::get().submitThen(
        []() -> std::string {
          SDL_Log("Async init task on main thread: %s",
                  TaskSystem::get().isMainThread() ? "true" : "false");

          auto &pvf = PvfArchive::get();
          if (!pvf.open("assets/Script.pvf")) {
            throw std::runtime_error("Failed to open assets/Script.pvf");
          }
          pvf.init();

          auto &npk = NpkArchive::get();
          npk.setImagePackDirectory("assets/ImagePacks2");
          npk.setDefaultImg("sprite/interface/base.img", 0);
          npk.init();

          auto &archive = SoundPackArchive::get();
          archive.setSoundPackDirectory("assets/SoundPacks");
          archive.init();

          return "后台资源加载成功";
        },
        [](std::string message) mutable {
          SDL_Log("后台资源加载成功");

          auto TestScene = MakePtr<Scene>();
          SceneManager::get().PushScene(TestScene);
        },
        [](std::exception_ptr error) {
          try {
            if (error) {
              std::rethrow_exception(error);
            }
          } catch (const std::exception &ex) {
            SDL_LogError(SDL_LOG_CATEGORY_APPLICATION, "Async init failed: %s",
                         ex.what());
          }
        });
  });

  SDL_Log("Application exited normally");
  app.shutdown();

  return 0;
}
