// 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 = M_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());
}
