#ifdef _WIN32
#define EXT_LINK
#endif

#define EXT_INC
#include "build.hpp"
#include <unordered_set>

#ifdef _WIN32
std::vector<std::string> LINK = {"-lopengl32", "-lkernel32", "-luser32", "-lshell32","-lwinmm","-lgdi32"};
#endif
std::vector<std::string> RAYINCLUDE = {"-Iraylib/src", "-Iraylib/src/external/glfw/include", "-Iraylib/src/external/glfw/deps/mingw"};
std::filesystem::path RAYLIB_DIR = "raylib";

bool build = false;
bool clear = false;
bool run = false;

void compile_raylib_dir()
{
  std::filesystem::path out_dir = OBJ_DIR / RAYLIB_DIR;
  std::filesystem::path ray_src_dir = RAYLIB_DIR / "src";
  std::filesystem::create_directory(out_dir);
  std::vector<std::filesystem::path> ray_srcs = {"rcore.c", "rshapes.c", "rtextures.c", "rtext.c", "utils.c", "rmodels.c", "raudio.c", "rglfw.c"};
  std::vector<std::string> ray_flags = {"-D_GNU_SOURCE", "-DPLATFORM_DESKTOP", "-DGRAPHICS_API_OPENGL_33"};

  command.clear();
  command.push_back(c_compiler);
  command.push_back("-c");
  int src_loc = command.size();
  command.push_back("");
  command.push_back("-o");
  int obj_loc = command.size();
  command.push_back("");

  command.insert(command.end(), ray_flags.begin(), ray_flags.end());
  command.push_back(opt_flags);
  command.insert(command.end(), RAYINCLUDE.begin(), RAYINCLUDE.end());

  std::filesystem::path out, src;

  for (size_t i = 0; i < ray_srcs.size(); i++)
  {
    src = ray_src_dir / ray_srcs[i];
    out = out_dir / ray_srcs[i].replace_extension(".o");
    if (check_if_rebuild(src, out))
    {
      command[src_loc] = src.string();
      command[obj_loc] = out.string();
      nob_cmd_run_sync(command);
    }
  }
}

int main(int argc, char const *argv[])
{
  if (rebuild_my_self(__FILE__, argc, argv))
    return 0;

  for (int i = 1; i < argc; ++i)
  {
    if (!std::strcmp(argv[i], "opt"))
      opt_flags = "-O3";

    if (!std::strcmp(argv[i], "build"))
      build = true;

    if (!std::strcmp(argv[i], "run"))
      run = true;

    if (!std::strcmp(argv[i], "clear"))
    {
      clear_all_build();
      clear = true;
    }
  }

  if (clear && !build)
  {
    return 0;
  }

  if (!std::filesystem::is_directory(RAYLIB_DIR))
  {
    command = {"git", "clone", "--depth", "1", "--branch", "5.0", "https://github.com/raysan5/raylib.git"};
    nob_cmd_run_sync(command);
    std::filesystem::remove_all("raylib/.git");
  }

  if (!std::filesystem::is_directory(RAYLIB_DIR))
    return 0;

  std::filesystem::create_directory(OBJ_DIR);

  compile_raylib_dir();

  int res = compile_src_dir(RAYINCLUDE);
  switch (res)
  {
  case 1:
    compile_obj_dir(LINK);
    break;
  case -1:
    return 0;
  }

  if (!std::filesystem::exists(BUILD_FILE))
    compile_obj_dir(LINK);

  if (run)
  {
    command = {"./" + BUILD_FILE.string()};
    nob_cmd_run_sync(command);
  }
  return 0;
}