// This file is part of Eigen, a lightweight C++ template library
// for linear algebra.
//
// Copyright (C) 2008 Gael Guennebaud <gael.guennebaud@inria.fr>
//
// This Source Code Form is subject to the terms of the Mozilla
// Public License v. 2.0. If a copy of the MPL was not distributed
// with this file, You can obtain one at http://mozilla.org/MPL/2.0/.

#include "camera.h"

#include "gpuhelper.h"
#include <GL/glu.h>

#include "Eigen/LU"
using namespace Eigen;

Camera::Camera() : mViewIsUptodate(false), mProjIsUptodate(false) {
  mViewMatrix.setIdentity();

  mFovY = EIGEN_PI / 3.;
  mNearDist = 1.;
  mFarDist = 50000.;

  mVpX = 0;
  mVpY = 0;

  setPosition(Vector3f::Constant(100.));
  setTarget(Vector3f::Zero());
}

Camera& Camera::operator=(const Camera& other) {
  mViewIsUptodate = false;
  mProjIsUptodate = false;

  mVpX = other.mVpX;
  mVpY = other.mVpY;
  mVpWidth = other.mVpWidth;
  mVpHeight = other.mVpHeight;

  mTarget = other.mTarget;
  mFovY = other.mFovY;
  mNearDist = other.mNearDist;
  mFarDist = other.mFarDist;

  mViewMatrix = other.mViewMatrix;
  mProjectionMatrix = other.mProjectionMatrix;

  return *this;
}

Camera::Camera(const Camera& other) { *this = other; }

Camera::~Camera() {}

void Camera::setViewport(uint offsetx, uint offsety, uint width, uint height) {
  mVpX = offsetx;
  mVpY = offsety;
  mVpWidth = width;
  mVpHeight = height;

  mProjIsUptodate = false;
}

void Camera::setViewport(uint width, uint height) {
  mVpWidth = width;
  mVpHeight = height;

  mProjIsUptodate = false;
}

void Camera::setFovY(float value) {
  mFovY = value;
  mProjIsUptodate = false;
}

Vector3f Camera::direction(void) const { return -(orientation() * Vector3f::UnitZ()); }
Vector3f Camera::up(void) const { return orientation() * Vector3f::UnitY(); }
Vector3f Camera::right(void) const { return orientation() * Vector3f::UnitX(); }

void Camera::setDirection(const Vector3f& newDirection) {
  // TODO implement it computing the rotation between newDirection and current dir ?
  Vector3f up = this->up();

  Matrix3f camAxes;

  camAxes.col(2) = (-newDirection).normalized();
  camAxes.col(0) = up.cross(camAxes.col(2)).normalized();
  camAxes.col(1) = camAxes.col(2).cross(camAxes.col(0)).normalized();
  setOrientation(Quaternionf(camAxes));

  mViewIsUptodate = false;
}

void Camera::setTarget(const Vector3f& target) {
  mTarget = target;
  if (!mTarget.isApprox(position())) {
    Vector3f newDirection = mTarget - position();
    setDirection(newDirection.normalized());
  }
}

void Camera::setPosition(const Vector3f& p) {
  mFrame.position = p;
  mViewIsUptodate = false;
}

void Camera::setOrientation(const Quaternionf& q) {
  mFrame.orientation = q;
  mViewIsUptodate = false;
}

void Camera::setFrame(const Frame& f) {
  mFrame = f;
  mViewIsUptodate = false;
}

void Camera::rotateAroundTarget(const Quaternionf& q) {
  Matrix4f mrot, mt, mtm;

  // update the transform matrix
  updateViewMatrix();
  Vector3f t = mViewMatrix * mTarget;

  mViewMatrix = Translation3f(t) * q * Translation3f(-t) * mViewMatrix;

  Quaternionf qa(mViewMatrix.linear());
  qa = qa.conjugate();
  setOrientation(qa);
  setPosition(-(qa * mViewMatrix.translation()));

  mViewIsUptodate = true;
}

void Camera::localRotate(const Quaternionf& q) {
  float dist = (position() - mTarget).norm();
  setOrientation(orientation() * q);
  mTarget = position() + dist * direction();
  mViewIsUptodate = false;
}

void Camera::zoom(float d) {
  float dist = (position() - mTarget).norm();
  if (dist > d) {
    setPosition(position() + direction() * d);
    mViewIsUptodate = false;
  }
}

void Camera::localTranslate(const Vector3f& t) {
  Vector3f trans = orientation() * t;
  setPosition(position() + trans);
  setTarget(mTarget + trans);

  mViewIsUptodate = false;
}

void Camera::updateViewMatrix(void) const {
  if (!mViewIsUptodate) {
    Quaternionf q = orientation().conjugate();
    mViewMatrix.linear() = q.toRotationMatrix();
    mViewMatrix.translation() = -(mViewMatrix.linear() * position());

    mViewIsUptodate = true;
  }
}

const Affine3f& Camera::viewMatrix(void) const {
  updateViewMatrix();
  return mViewMatrix;
}

void Camera::updateProjectionMatrix(void) const {
  if (!mProjIsUptodate) {
    mProjectionMatrix.setIdentity();
    float aspect = float(mVpWidth) / float(mVpHeight);
    float theta = mFovY * 0.5;
    float range = mFarDist - mNearDist;
    float invtan = 1. / tan(theta);

    mProjectionMatrix(0, 0) = invtan / aspect;
    mProjectionMatrix(1, 1) = invtan;
    mProjectionMatrix(2, 2) = -(mNearDist + mFarDist) / range;
    mProjectionMatrix(3, 2) = -1;
    mProjectionMatrix(2, 3) = -2 * mNearDist * mFarDist / range;
    mProjectionMatrix(3, 3) = 0;

    mProjIsUptodate = true;
  }
}

const Matrix4f& Camera::projectionMatrix(void) const {
  updateProjectionMatrix();
  return mProjectionMatrix;
}

void Camera::activateGL(void) {
  glViewport(vpX(), vpY(), vpWidth(), vpHeight());
  gpu.loadMatrix(projectionMatrix(), GL_PROJECTION);
  gpu.loadMatrix(viewMatrix().matrix(), GL_MODELVIEW);
}

Vector3f Camera::unProject(const Vector2f& uv, float depth) const {
  Matrix4f inv = mViewMatrix.inverse().matrix();
  return unProject(uv, depth, inv);
}

Vector3f Camera::unProject(const Vector2f& uv, float depth, const Matrix4f& invModelview) const {
  updateViewMatrix();
  updateProjectionMatrix();

  Vector3f a(2. * uv.x() / float(mVpWidth) - 1., 2. * uv.y() / float(mVpHeight) - 1., 1.);
  a.x() *= depth / mProjectionMatrix(0, 0);
  a.y() *= depth / mProjectionMatrix(1, 1);
  a.z() = -depth;
  // FIXME /\/|
  Vector4f b = invModelview * Vector4f(a.x(), a.y(), a.z(), 1.);
  return Vector3f(b.x(), b.y(), b.z());
}
