#pragma once

#include "pxl8_math.h"
#include "pxl8_types.h"

typedef enum pxl8_3d_camera_mode {
    PXL8_3D_CAMERA_ORTHO,
    PXL8_3D_CAMERA_PERSPECTIVE
} pxl8_3d_camera_mode;

typedef struct pxl8_3d_camera pxl8_3d_camera;

#ifdef __cplusplus
extern "C" {
#endif

pxl8_3d_camera* pxl8_3d_camera_create(void);
void pxl8_3d_camera_destroy(pxl8_3d_camera* cam);

void pxl8_3d_camera_lookat(pxl8_3d_camera* cam, pxl8_vec3 eye, pxl8_vec3 target, pxl8_vec3 up);
void pxl8_3d_camera_set_ortho(pxl8_3d_camera* cam, f32 left, f32 right, f32 bottom, f32 top, f32 near, f32 far);
void pxl8_3d_camera_set_perspective(pxl8_3d_camera* cam, f32 fov, f32 aspect, f32 near, f32 far);
void pxl8_3d_camera_set_position(pxl8_3d_camera* cam, pxl8_vec3 pos);
void pxl8_3d_camera_set_rotation(pxl8_3d_camera* cam, f32 pitch, f32 yaw, f32 roll);

pxl8_vec3 pxl8_3d_camera_get_forward(const pxl8_3d_camera* cam);
pxl8_vec3 pxl8_3d_camera_get_position(const pxl8_3d_camera* cam);
pxl8_mat4 pxl8_3d_camera_get_projection(const pxl8_3d_camera* cam);
pxl8_vec3 pxl8_3d_camera_get_right(const pxl8_3d_camera* cam);
pxl8_vec3 pxl8_3d_camera_get_up(const pxl8_3d_camera* cam);
pxl8_mat4 pxl8_3d_camera_get_view(const pxl8_3d_camera* cam);

void pxl8_3d_camera_blend(pxl8_3d_camera* dest, const pxl8_3d_camera* a, const pxl8_3d_camera* b, f32 t);
void pxl8_3d_camera_follow(pxl8_3d_camera* cam, pxl8_vec3 target, pxl8_vec3 offset, f32 smoothing, f32 dt);
pxl8_projected_point pxl8_3d_camera_world_to_screen(const pxl8_3d_camera* cam, pxl8_vec3 world_pos, u32 screen_width, u32 screen_height);
void pxl8_3d_camera_shake(pxl8_3d_camera* cam, f32 intensity, f32 duration);
void pxl8_3d_camera_update(pxl8_3d_camera* cam, f32 dt);

#ifdef __cplusplus
}
#endif
