#pragma once

#include <glm/glm.hpp>
#include <glm/gtc/matrix_transform.hpp>

#include "../util/types.hpp"

struct CameraInfo {
  alignas(16) glm::vec3 position; ///< Camera position
};

/**
 * @brief Camera class for handling 3D camera movement and perspective
 */
class Camera {
 public:
  Camera();

  [[nodiscard]] fn getPosition() const -> glm::dvec3;
  [[nodiscard]] fn getFront() const -> glm::dvec3;
  [[nodiscard]] fn getYaw() const -> f64;
  [[nodiscard]] fn getPitch() const -> f64;
  [[nodiscard]] fn getViewMatrix() const -> glm::mat4;

  fn moveForward(f64 deltaTime) -> void;
  fn moveBackward(f64 deltaTime) -> void;
  fn moveLeft(f64 deltaTime) -> void;
  fn moveRight(f64 deltaTime) -> void;
  fn moveUp(f64 deltaTime) -> void;
  fn moveDown(f64 deltaTime) -> void;
  fn rotate(f64 xoffset, f64 yoffset) -> void;

 private:
  fn updateCameraVectors() -> void;

  glm::dvec3 mPosition;
  glm::dvec3 mFront;
  glm::dvec3 mUp;
  glm::dvec3 mRight;
  f64        mYaw;
  f64        mPitch;
};
