/*
 * Copyright 2017 The Cobalt Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "cobalt/input/camera_3d_input_poller.h"

#include <algorithm>
#include <cmath>

#include "cobalt/input/create_default_camera_3d.h"
#include "third_party/glm/glm/gtc/matrix_transform.hpp"
#include "third_party/glm/glm/gtc/quaternion.hpp"
#include "third_party/glm/glm/gtx/transform.hpp"

namespace cobalt {
namespace input {

Camera3DInputPoller::Camera3DInputPoller(
    const scoped_refptr<input::InputPoller>& input_poller)
    : roll_in_radians_(0.0f),
      pitch_in_radians_(0.0f),
      yaw_in_radians_(0.0f),
      input_poller_(input_poller),
      width_to_height_aspect_ratio_(16.0f / 9.0f),
      vertical_fov_(60.0f) {}

void Camera3DInputPoller::CreateKeyMapping(int keycode, uint32 camera_axis,
                                           float degrees_per_second) {
  base::AutoLock lock(mutex_);
  keycode_map_[keycode] = KeycodeMappingInfo(camera_axis, degrees_per_second);
}

void Camera3DInputPoller::ClearKeyMapping(int keycode) {
  base::AutoLock lock(mutex_);
  keycode_map_.erase(keycode);
}

void Camera3DInputPoller::ClearAllKeyMappings() {
  base::AutoLock lock(mutex_);
  keycode_map_.clear();
}

glm::quat Camera3DInputPoller::orientation() const {
  return glm::angleAxis(-roll_in_radians_, glm::vec3(0, 0, 1)) *
         glm::angleAxis(-pitch_in_radians_, glm::vec3(1, 0, 0)) *
         glm::angleAxis(-yaw_in_radians_, glm::vec3(0, 1, 0));
}

glm::quat Camera3DInputPoller::GetOrientation() const {
  base::AutoLock lock(mutex_);
  return orientation();
}

base::CameraTransform
Camera3DInputPoller::GetCameraTransformAndUpdateOrientation() {
  base::AutoLock lock(mutex_);
  AccumulateOrientation();

  glm::mat4 view_matrix = glm::mat4_cast(orientation());

  const float kNearZ = 0.01f;
  const float kFarZ = 1000.0f;
  glm::mat4 projection_matrix = glm::perspectiveRH(
      vertical_fov_, width_to_height_aspect_ratio_, kNearZ, kFarZ);

  return base::CameraTransform(projection_matrix, view_matrix);
}

void Camera3DInputPoller::UpdatePerspective(float width_to_height_aspect_ratio,
                                            float vertical_fov) {
  width_to_height_aspect_ratio_ = width_to_height_aspect_ratio;
  vertical_fov_ = vertical_fov;
}

void Camera3DInputPoller::Reset() {
  base::AutoLock lock(mutex_);
  roll_in_radians_ = 0.0f;
  pitch_in_radians_ = 0.0f;
  yaw_in_radians_ = 0.0f;
}

void Camera3DInputPoller::AccumulateOrientation() {
  if (!input_poller_) {
    // Nothing to do if no input poller was provided.
    return;
  }

  base::TimeTicks now = base::TimeTicks::Now();
  if (last_update_) {
    base::TimeDelta delta = now - *last_update_;
    // Cap out the maximum time delta that we will accumulate changes over, to
    // avoid a random extra long time delta that completely changes the camera
    // orientation.
    const base::TimeDelta kMaxTimeDelta = base::TimeDelta::FromMilliseconds(40);
    if (delta > kMaxTimeDelta) {
      delta = kMaxTimeDelta;
    }

    // Accumulate new rotation from all mapped inputs.
    for (KeycodeMap::const_iterator iter = keycode_map_.begin();
         iter != keycode_map_.end(); ++iter) {
      // If the key does not have analog output, the AnalogInput() method will
      // always return 0.0f, so check this first, and if it is indeed 0,
      // fallback to a check to see if the button is digital and pressed.
      float value = input_poller_->AnalogInput(static_cast<SbKey>(iter->first));
      if (value == 0.0f) {
        value = input_poller_->IsPressed(static_cast<SbKey>(iter->first))
                    ? 1.0f
                    : 0.0f;
      }

      // Get a pointer to the camera axis angle that this key is bound to.
      float* target_angle;
      switch (iter->second.axis) {
        case kCameraRoll:
          target_angle = &roll_in_radians_;
          break;
        case kCameraPitch:
          target_angle = &pitch_in_radians_;
          break;
        case kCameraYaw:
          target_angle = &yaw_in_radians_;
          break;
      }

      // Apply the angle adjustment from the key.
      *target_angle += value *
                       DegreesToRadians(iter->second.degrees_per_second) *
                       static_cast<float>(delta.InSecondsF());
    }

    // Clamp the angles to ensure that they remain in the valid range.
    ClampAngles();
  }
  last_update_ = now;
}

void Camera3DInputPoller::ClampAngles() {
  float kTwoPi = static_cast<float>(M_PI * 2);
  float kPiOverTwo = static_cast<float>(M_PI / 2);

  pitch_in_radians_ =
      std::max(-kPiOverTwo, std::min(kPiOverTwo, pitch_in_radians_));

  roll_in_radians_ = fmod(roll_in_radians_, kTwoPi);
  if (roll_in_radians_ < 0) {
    roll_in_radians_ += kTwoPi;
  }

  yaw_in_radians_ = fmod(yaw_in_radians_, kTwoPi);
  if (yaw_in_radians_ < 0) {
    yaw_in_radians_ += kTwoPi;
  }
}

scoped_refptr<Camera3D> CreatedDefaultCamera3D(
    SbWindow window, const scoped_refptr<InputPoller>& input_poller) {
  return new Camera3DInputPoller(input_poller);
}

}  // namespace input
}  // namespace cobalt
