#pragma once

#include "ShaderProgram.h"
#include <glm/vec3.hpp>
#include <glm/gtc/matrix_transform.hpp>

namespace logic {
	/*!
		Camera in the world
	*/
	class Camera
	{
	public:
		Camera();
		/*!
			Initializes a camera with a given movement \a speed.
			\a screenRation is given as width / height
			\a FOV is the field of view. PI/4 is just fine.
			\a nearZ is the z of the near plane. 0.5 is fine.
			\a farZ is z of the far plane. 100 is fine.
			\a position is the position of the camera in world space
			\a direction is the direction of the camera (where it points)
			\a upAxis is the up direction (normally 0 1 0).
		*/
		Camera(float speed, float screenRatio, float FOV, float nearZ, float farZ, const glm::vec3 & position, const glm::vec3 & direction, const glm::vec3 & upAxis);
		/*!
			returns full UVN transformation
		*/
		glm::mat4 getTransformation() const;
		/*!
			returns the orientation transformation without the needed translation.
			This can be used when selecting the color of the skybox.
		*/
		glm::mat4 getOrientationTransformation() const;
		/*!
			moves the camera by \a delta x speed
		*/
		void move(const glm::vec3 & delta);
		/*!
			rotates the camera by dx and dy degrees
		*/
		void orientate(int dx, int dy);
		/*!
			returns the position of the camera
		*/
		glm::vec3 getPosition() const;
		/*!
			returns the direction of the camera
		*/
		glm::vec3 getDirection() const;
		/*!
			updates the frustrum transformation in the \a program
		*/
		void feedFrustrum(graphics::ShaderProgram * program) const;
		/*!
			returns the projection transformation
		*/
		glm::mat4 getProjectionTransformation() const;
		/*!
			returns othogonal projection
		*/
		glm::mat4 getOrthoTransformation() const;
		/*!
			feeds the uvn matrix into the shader
		*/
		void feedUVN(graphics::ShaderProgram * program) const;
		/*!
			feeds camera position, eye
		*/
		void feedCameraData(graphics::ShaderProgram * program) const;

		void updateOrientation();
	
		glm::vec3 m_position;
		glm::vec3 m_originalPosition;
		glm::vec3 m_direction;
		glm::vec3 m_upAxis;
		glm::vec3 m_originalDirection;
		glm::vec3 m_originalUpAxis;
		float m_verticalAngleRad;
		float m_horizontalAngleRad;
		float m_screenRatio;
		float m_FOV;
		float m_nearZ;
		float m_farZ;
		float m_speed;
	};

};