#include "raylib.h"
#include <cmath>
#include <string>

#ifdef __APPLE__
#include <mach-o/dyld.h>
#include <unistd.h>
#include <libgen.h>
#endif

// Global state
Model pengerModel;

Camera3D camera = { 0 };

Vector2 mouseDelta = { 0 };

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

void CalculateFrame() {
    mouseDelta = GetMouseDelta();
    
    // Zoom on scroll
    float wheelMove = GetMouseWheelMove();
    cameraRadius -= wheelMove * 1.5f;
    if (cameraRadius < 2.0f)  cameraRadius = 2.0f;
    if (cameraRadius > 50.0f) cameraRadius = 50.0f;

    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;

    Vector3 newCameraPosition;
    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(pengerModel, (Vector3){ 0.0f, 0.0f, 0.0f }, 1.0f, WHITE);
            DrawGrid(10, 1.0f);
        EndMode3D();

        DrawFPS(10, 10);
    EndDrawing();
}

// Resolve the directory containing this executable.
// On macOS this handles both command-line runs and double-clicked .app bundles.
std::string GetExecutableDir() {
#ifdef __APPLE__
    char path[1024];
    uint32_t size = sizeof(path);
    if (_NSGetExecutablePath(path, &size) == 0) {
        char *dir = dirname(path);          // strip executable name
        char *real = realpath(dir, nullptr); // resolve symlinks
        std::string result(real);
        free(real);
        return result;
    }
#endif
    return ".";
}

int main() {
    // Move working directory next to the executable so relative asset
    // paths work both from the command line and inside a .app bundle.
    chdir(GetExecutableDir().c_str());

    SetConfigFlags(FLAG_WINDOW_RESIZABLE | FLAG_MSAA_4X_HINT);

    InitWindow(1280, 720, "Penger — Native");
    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);

    pengerModel = LoadModel("assets/penger.obj");

    while (!WindowShouldClose()) {
        CalculateFrame();
        DrawFrame();
    }

    UnloadModel(pengerModel);
    CloseWindow();

    return 0;
}
