#include "Camera.h"

#include "Math/Matrix.h"

#include "GL/glfw.h"

namespace BlueCore
{

//--------------------------------------------------------------------------
Camera::Camera()
{
}

//--------------------------------------------------------------------------
Camera::~Camera()
{
}

//--------------------------------------------------------------------------
void Camera::setFoV(Scalar fov)
{
  _FoV = fov;
}

//--------------------------------------------------------------------------
void Camera::setAspectRatio(Scalar aspect)
{
  _AspectRatio = aspect;
}

//--------------------------------------------------------------------------
void Camera::setNearPlane(Scalar near)
{
  _NearPlane = near;
}

//--------------------------------------------------------------------------
void Camera::setFarPlane(Scalar far)
{
  _FarPlane = far;
}

//--------------------------------------------------------------------------
void Camera::setPosition(const Vector3& position)
{
  _Position = position;
}

const Vector3& Camera::getPosition()
{
  return _Position;
}

//--------------------------------------------------------------------------
void Camera::setRotation(const Quaternion& rotation)
{
  _Rotation = rotation;
}

//--------------------------------------------------------------------------
void Camera::setupProjectionMatrix()
{
  Scalar fW, fH;

  fH = tan ( (_FoV / 2) / 180* Pi ) * _NearPlane;
  fW = fH * _AspectRatio;

  // setup projectiom matrix
  glMatrixMode (GL_PROJECTION );
  glLoadIdentity();
  glFrustum ( -fW, fW, -fH, fH, _NearPlane, _FarPlane );

  // save variables for frustum culling
  /*
   _near = nearZ;
   _far = farZ;
   _hNear = tan ( ( fov / 2 ) / 180 * Pi ) * nearZ;
   _wNear = _hNear * aspect;
   _hFar = tan ( ( fov / 2 ) / 180 * Pi ) * farZ;
   _wFar = _hFar * aspect;
   */
}

//--------------------------------------------------------------------------
void Camera::setupViewMatrix()
{
  // set the view matrix
  glMatrixMode (GL_MODELVIEW );
  glLoadIdentity();
  Matrix4x4 m(_Rotation, _Rotation.applyInversed(_Position * -1.0) );
  glMultMatrixd ( ( GLdouble * ) &m.m );
  /*
   // calculate frustum planes
   Vector3 up = q.apply ( Vector3 ( 0.0, 1.0, 0.0 ) );
   Vector3 right = q.apply ( Vector3 ( 1.0, 0.0, 0.0 ) );
   Vector3 d = q.apply ( Vector3 ( 0.0, 0.0, -1.0 ) );

   Vector3 fc = p + d * _far;

   Vector3 ftl = fc + ( up * _hFar ) - ( right * _wFar );
   Vector3 ftr = fc + ( up * _hFar ) + ( right * _wFar );
   Vector3 fbl = fc - ( up * _hFar ) - ( right * _wFar );
   Vector3 fbr = fc - ( up * _hFar ) + ( right * _wFar );

   Vector3 nc = p + d * _near;

   Vector3 ntl = nc + ( up * _hNear ) - ( right * _wNear );
   Vector3 ntr = nc + ( up * _hNear ) + ( right * _wNear );
   Vector3 nbl = nc - ( up * _hNear ) - ( right * _wNear );
   Vector3 nbr = nc - ( up * _hNear ) + ( right * _wNear );

   _frustumPlanes[RightPlane] = Plane ( nbr, fbr, ntr );
   _frustumPlanes[LeftPlane] = Plane ( ntl, fbl, nbl );
   _frustumPlanes[BottomPlane] = Plane ( nbl, fbr, nbr );
   _frustumPlanes[TopPlane] = Plane ( ntr, ftl, ntl );
   _frustumPlanes[FarPlane] = Plane ( ftl, ftr, fbl );
   _frustumPlanes[NearPlane] = Plane ( ntl, nbl, ntr );
   */
}

} // namespace BlueCore

