#include <GL/glew.h>
#include <GLFW/glfw3.h>
#include <iostream>
#include <chrono>
#include <thread>

#include <imgui.h>
#include <imgui_impl_glfw.h>
#include <imgui_impl_opengl3.h>

#include "scene.h"

const int TARGET_FPS = 60;
const auto FRAME_DURATION = std::chrono::milliseconds(1000 / TARGET_FPS);

int main(){
  if (!glfwInit()) {
    std::cerr << "Failed to initialize GLFW" << std::endl;
    return -1;
  }

  GLFWwindow* window = glfwCreateWindow(1280, 720, "TerraVisor", nullptr, nullptr);
  if(!window) {
    std::cerr << "Failed to create GLFW window" << std::endl;
    glfwTerminate();
    return -1;
  }

  glfwMakeContextCurrent(window);
  glewExperimental = GL_TRUE;
  if(glewInit() != GLEW_OK) {
    std::cerr << "Failed to initialize GLEW" << std::endl;
    return -1;
  }

  Scene::Init();

  //Init ImGui
  IMGUI_CHECKVERSION();
  ImGui::CreateContext();
  ImGui_ImplGlfw_InitForOpenGL(window, true);
  ImGui_ImplOpenGL3_Init("#version 150");

  auto lastFrameTime = std::chrono::high_resolution_clock::now();
  
  while (!glfwWindowShouldClose(window)) {
    auto frameStart = std::chrono::high_resolution_clock::now();

    Scene::Idle();
    Scene::Display(window);
    
    glfwPollEvents();

    auto frameEnd = std::chrono::high_resolution_clock::now();
    auto frameDuration = frameEnd - frameStart;

    if (frameDuration < FRAME_DURATION) {
      std::this_thread::sleep_for(FRAME_DURATION - frameDuration);
    }

    auto currentFrameTime = std::chrono::high_resolution_clock::now();
    auto actualFrameDuration = std::chrono::duration_cast<std::chrono::milliseconds>(currentFrameTime - lastFrameTime).count();

    lastFrameTime = currentFrameTime;
  }

  // Cleanup ImGui
  ImGui_ImplOpenGL3_Shutdown();
  ImGui_ImplGlfw_Shutdown();
  ImGui::DestroyContext();

  glfwDestroyWindow(window);
  glfwTerminate();
  return 0;
}
