#include "camera.h"
#include "canvas.h"
#include "simulation.h"
#include <SDL2/SDL.h>
#include <chrono>
#include <thread>

int main() {
  auto aspect_ratio = 16.0 / 9.0;
  int image_width = 400;

  // Calculate the image height, and ensure that it's at least 1.
  int image_height = int(image_width / aspect_ratio);
  image_height = (image_height < 1) ? 1 : image_height;

  Canvas canvas(image_width, image_height);
  RingBuffer<SimulationState> buffer(64);
  Camera cam;
  cam.aspect_ratio = 16.0 / 9.0;
  cam.image_width = 400;
  cam.move_to(Point3(0, 10, 100));

  std::thread sim(simulation_thread, std::ref(buffer));
  std::thread render(render_thread, std::ref(buffer), std::ref(canvas),
                     std::ref(cam));

  SDL_Init(SDL_INIT_VIDEO);
  int scale = 3;
  SDL_Window *window = SDL_CreateWindow(
      "Solar System", SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
      canvas.width * scale,  // window width
      canvas.height * scale, // window height
      SDL_WINDOW_RESIZABLE   // optional, allows manual resize
  );
  SDL_Renderer *renderer =
      SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED);
  SDL_Texture *texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGB24,
                                           SDL_TEXTUREACCESS_STREAMING,
                                           canvas.width, canvas.height);

  float camera_speed = 10.0f; // tweak as needed

  while (running) {
    void *pixels;
    int pitch;
    SDL_LockTexture(texture, nullptr, &pixels, &pitch);
    memcpy(pixels, canvas.pixels.data(), canvas.pixels.size() * sizeof(Rgb));
    SDL_UnlockTexture(texture);

    SDL_RenderClear(renderer);
    SDL_Rect dest = {0, 0, canvas.width * scale, canvas.height * scale};
    SDL_RenderCopy(renderer, texture, nullptr, &dest);
    SDL_RenderPresent(renderer);

    Point3 move(0, 0, 0);

    SDL_Event e;
    while (SDL_PollEvent(&e)) {
      if (e.type == SDL_QUIT) {
        running = false;
      } else if (e.type == SDL_KEYDOWN) {
        switch (e.key.keysym.sym) {
        case SDLK_w:
          move.z() -= camera_speed;
          break; // forward
        case SDLK_s:
          move.z() += camera_speed;
          break; // backward
        case SDLK_a:
          move.x() -= camera_speed;
          break; // left
        case SDLK_d:
          move.x() += camera_speed;
          break; // right
        case SDLK_q:
          move.y() += camera_speed;
          break; // up
        case SDLK_e:
          move.y() -= camera_speed;
          break; // down
        }

        cam.move_to(cam.position() + move); // assuming cam.position exists
      }
    }

    std::this_thread::sleep_for(std::chrono::milliseconds(16)); // ~60fps
  }

  sim.join();
  render.join();
}
