#pragma once

// orbit_camera — camara orbital pura. Estado minimo (azimuth, elevation,
// distance, fov, aspect, near/far) y dos helpers: matrices view/proj y
// handle_drag para integrar drag/wheel del mouse.
//
// Las matrices se devuelven como float[16] row-major, pero al subirlas a
// OpenGL con glUniformMatrix4fv hay que pasar transpose=GL_TRUE (porque
// GL espera column-major). Ver mesh_viewer.cpp para el patron.

struct ImVec2;  // fwd-decl, definido por imgui.h

namespace fn::core {

struct OrbitCamera {
    float azimuth     = 0.7f;   // rad, rotacion en plano XZ
    float elevation   = 0.4f;   // rad, rotacion en plano YZ, clamp ±π/2-eps
    float distance    = 3.0f;   // distancia al origen (target=0,0,0)
    float fov         = 45.0f;  // grados, vertical FOV
    float aspect      = 1.0f;   // width/height del viewport
    float near_plane  = 0.05f;
    float far_plane   = 100.0f;
};

struct CameraMatrices {
    float view[16];   // row-major
    float proj[16];   // row-major
};

// Calcula view (lookAt eye→origin, up=Y) y proj (perspective). Pure.
CameraMatrices orbit_camera_matrices(const OrbitCamera& cam);

// Aplica un drag de mouse (dx,dy) y rueda (wheel) sobre la camara.
// dx → azimuth (sensibilidad 0.01 rad/px)
// dy → elevation (clamp a ±π/2 - 1e-3)
// wheel → distance *= (1 - wheel*0.1), clamp >0.1
// Pure (sin side effects mas alla de mutar la struct in-place).
void orbit_camera_handle_drag(OrbitCamera& cam, ImVec2 drag_delta, float wheel);

} // namespace fn::core
