#include "raylib.h"
#include <emscripten/emscripten.h>
#include <iostream>
#include <cmath>

// Global state
Texture2D cubeTexture;
Model cubeModel;

Camera3D camera = { 0 };

Vector2 mouseDelta = { 0 };

float cameraSpeed = 0.8f;
float cameraPosition = 10.0f;
float cameraRadius = 0.0f;
Vector2 cameraAngle;

void CalculateFrame() {
    mouseDelta = GetMouseDelta();
    
    Vector3 originalCameraPosition = camera.position;
    Vector3 newCameraPosition = originalCameraPosition;

    cameraAngle.x += mouseDelta.x;
    cameraAngle.y += mouseDelta.y;

    if (cameraAngle.y > 89.0f) cameraAngle.y = 90.0f;
    if (cameraAngle.y < -89.0f) cameraAngle.y = -90.0f;

    float mouseDeltaRadianX = (cameraAngle.x * (PI / 180.0f)) * cameraSpeed;
    float mouseDeltaRadianY = (cameraAngle.y * (PI / 180.0f)) * cameraSpeed;

    newCameraPosition.x = cameraRadius * cosf(mouseDeltaRadianX) * cosf(mouseDeltaRadianY);
    newCameraPosition.z = cameraRadius * sinf(mouseDeltaRadianX) * cosf(mouseDeltaRadianY);
    newCameraPosition.y = cameraRadius *                           sinf(mouseDeltaRadianY);

    camera.position = newCameraPosition;
}

void DrawFrame() {
    BeginDrawing();
    ClearBackground(DARKGRAY);
        BeginMode3D(camera);
            DrawModel(cubeModel, (Vector3){ 0.0f, 0.0f, 0.0f }, 1.0f, WHITE);
            DrawCubeWires((Vector3){ 0, 0, 0 }, 2.0f, 2.0f, 2.0f, MAROON);
            DrawGrid(10, 1.0f);
        EndMode3D();

        DrawFPS(10, GetScreenHeight() - GetScreenHeight() + 10);
    EndDrawing();
}

void UpdateDrawFrame() {
    CalculateFrame();
    DrawFrame();
}

int main() {
    // Enable High DPI for crisp rendering on Retina displays
    SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_MSAA_4X_HINT | FLAG_WINDOW_HIGHDPI);
    
    // Internal resolution
    InitWindow(2560, 1440, "Raylib WASM");
    SetTargetFPS(60);

    camera.position = (Vector3){ cameraPosition, cameraPosition, cameraPosition };
    camera.target = (Vector3){ 0.0f, 0.0f, 0.0f };
    camera.up = (Vector3){ 0.0f, 1.0f, 0.0f };
    camera.fovy = 45.0f;
    camera.projection = CAMERA_PERSPECTIVE;
    cameraRadius = cameraPosition * sqrt(3);

    Mesh mesh = GenMeshCube(2.0f, 2.0f, 2.0f);
    cubeModel = LoadModelFromMesh(mesh);
    cubeTexture = LoadTexture("assets/coding.png");

    cubeModel.materials[0].maps[MATERIAL_MAP_DIFFUSE].texture = cubeTexture;

    emscripten_set_main_loop(UpdateDrawFrame, 0, 1);

    // Note: This part is rarely reached in WASM
    UnloadTexture(cubeTexture);
    UnloadModel(cubeModel);
    CloseWindow();

    return 0;
}