#include "raylib.h"
#include "raymath.h"
#include "rcamera.h"

#if defined(PLATFORM_WEB)
    #include <emscripten/emscripten.h>
#endif

const int screen_width = 800;
const int screen_height = 450;

Camera camera = {0};
Ray ray = {0};
Model parth;
Texture2D texture;
Vector3 parth_pos = {0.0f, 0.0f, 0.0f};
BoundingBox parth_bound_box;

void MainGameLoop(void);

int main(int argc, char **argv)
{
  InitWindow(screen_width, screen_height, "Parthanon 3D");

  camera.position = (Vector3){-9.0f, 9.0f, 4.0f};
  camera.target = (Vector3){9.0f, 9.0f, 0.0f};
  camera.up = (Vector3){0.0f, 1.0f, 0.0f};
  camera.fovy = 60.0f;
  camera.projection = CAMERA_PERSPECTIVE;

  parth = LoadModel("resources/parthanon.obj");
  texture = LoadTexture("resources/parthanon.png");
  parth.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = texture;

  parth_bound_box = GetMeshBoundingBox(parth.meshes[0]);

#if defined(PLATFORM_WEB)
    emscripten_set_main_loop(MainGameLoop, 0, 1);
#else
    SetTargetFPS(60);   // Set our game to run at 60 frames-per-second

    DisableCursor();

    while (!WindowShouldClose())
    {
        MainGameLoop();
    }
#endif

  UnloadModel(parth);
  UnloadTexture(texture);

  CloseWindow();
  return 0;
}

/**
 * Main game loop
 */
void MainGameLoop(void)
{
    // Lock mouse cursor if mouse click on canvas
    if (IsMouseButtonPressed(MOUSE_LEFT_BUTTON)) DisableCursor();
    if (IsKeyPressed(KEY_ESCAPE)) EnableCursor();

    /* UpdateCamera(&camera, CAMERA_FIRST_PERSON); */

    UpdateCameraPro(&camera,
         (Vector3){
             (IsKeyDown(KEY_W) || IsKeyDown(KEY_UP))*0.1f -      // Move forward-backward
             (IsKeyDown(KEY_S) || IsKeyDown(KEY_DOWN))*0.1f,    
             (IsKeyDown(KEY_D) || IsKeyDown(KEY_RIGHT))*0.1f -   // Move right-left
             (IsKeyDown(KEY_A) || IsKeyDown(KEY_LEFT))*0.1f,
             0.0f                                                // Move up-down
         },
         (Vector3){
             GetMouseDelta().x*0.05f,                            // Rotation: yaw
             GetMouseDelta().y*0.05f,                            // Rotation: pitch
             0.0f                                                // Rotation: roll
         },
         GetMouseWheelMove()*2.0f);                              // Move to target (zoom)

    RayCollision collision = {0};
    collision.distance = 10000000.0f; // arbitrary reasonable distance.
    collision.hit = false;

    // ray pointing down so we are always just above the floor.
    ray = (Ray){camera.position, (Vector3){0.0f, -1.0f, 0.0f}};

    RayCollision bb_hit = GetRayCollisionBox(ray, parth_bound_box);
    if ((bb_hit.hit) && (bb_hit.distance < collision.distance))
    {
      collision = bb_hit;

      RayCollision mesh_collide = {0};
      for (int m = 0; m < parth.meshCount; m++)
      {
        mesh_collide = GetRayCollisionMesh(ray, parth.meshes[m], parth.transform);
        if (mesh_collide.hit)
	{
          if ((!collision.hit) || (collision.distance > mesh_collide.distance))
	  {
            collision = mesh_collide;
          }
          break;
        }
      }

      if (mesh_collide.hit)
      {
        collision = mesh_collide;
      }
    }

    BeginDrawing();

    ClearBackground(RAYWHITE);

    BeginMode3D(camera);

    DrawModel(parth, parth_pos, 1.0f, WHITE);

    if (collision.hit)
    {
      camera.position.y = collision.point.y + 0.4; // Camera position
      if (camera.position.y < 0.0f)
      {
        camera.position.y = 0.4f;
      }
    }

    DrawGrid(10, 10.0f);

    EndMode3D();

    DrawFPS(10, 10);

    EndDrawing();
}
