/*
 * 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/dom/camera_3d.h"

#include "base/basictypes.h"
#include "base/time/time.h"
#include "cobalt/dom/device_orientation_event.h"
#include "third_party/glm/glm/gtx/euler_angles.hpp"

namespace cobalt {
namespace dom {

Camera3D::Camera3D(const scoped_refptr<input::Camera3D>& impl)
    : impl_(impl),
      last_event_alpha_(720.0),
      last_event_beta_(720.0),
      last_event_gamma_(720.0) {}

void Camera3D::CreateKeyMapping(int keycode, uint32 camera_axis,
                                float degrees_per_second) {
  impl_->CreateKeyMapping(keycode, camera_axis, degrees_per_second);
}

void Camera3D::ClearKeyMapping(int keycode) { impl_->ClearKeyMapping(keycode); }

void Camera3D::ClearAllKeyMappings() { impl_->ClearAllKeyMappings(); }

void Camera3D::Reset() { impl_->Reset(); }

void Camera3D::StartOrientationEvents(
    const base::WeakPtr<web::EventTarget>& target) {
  if (!impl()) {
    return;
  }
  orientation_event_timer_.Start(
      FROM_HERE,
      base::TimeDelta::FromSecondsD(1.0 / ORIENTATION_POLL_FREQUENCY_HZ),
      base::Bind(&Camera3D::FireOrientationEvent, base::Unretained(this),
                 target));
}

void Camera3D::StopOrientationEvents() { orientation_event_timer_.Stop(); }

namespace {

// These produces angles within the ranges: alpha in [-180,180], beta in
// [-90,90], gamma in [-180,180].
static void QuaternionToIntrinsicZXY(const glm::dquat& q, double* intrinsic_z,
                                     double* intrinsic_x, double* intrinsic_y) {
  *intrinsic_z = atan2(2 * (q.x * q.y + q.w * q.z),
                       q.w * q.w - q.x * q.x + q.y * q.y - q.z * q.z);
  *intrinsic_x = asin(-2 * (q.y * q.z - q.w * q.x));
  *intrinsic_y = atan2(2 * (q.x * q.z + q.w * q.y),
                       q.w * q.w - q.x * q.x - q.y * q.y + q.z * q.z);
}

}  // namespace

void Camera3D::FireOrientationEvent(base::WeakPtr<web::EventTarget> target) {
  glm::dquat quaternion = glm::normalize(
      glm::dquat(impl()->GetOrientation()) *
      // The API assumes a different initial orientation (straight down instead
      // of ahead), requiring a previous rotation of 90 degrees.
      glm::angleAxis(M_PI / 2, glm::dvec3(1.0f, 0.0f, 0.0f)));

  double intrinsic_z = 0.0f, intrinsic_x = 0.0f, intrinsic_y = 0.0f;
  QuaternionToIntrinsicZXY(quaternion, &intrinsic_z, &intrinsic_x,
                           &intrinsic_y);

  // Adjust to the angle ranges specified by the Device Orientation API.
  // They should be: alpha in [0,360], beta in [-180,180], gamma in [-90,90].
  double alpha = input::Camera3D::RadiansToDegrees(intrinsic_z);
  double beta = input::Camera3D::RadiansToDegrees(intrinsic_x);
  double gamma = -input::Camera3D::RadiansToDegrees(intrinsic_y);

  if (gamma > 90 || gamma < -90) {
    gamma = copysign(180, gamma) - gamma;
    // Represent excess gamma as rotations along other axes.
    beta = 180 - beta;
    alpha = 180 - alpha;
  }

  alpha = fmod(360 + alpha, 360);
  beta = beta >= 180 ? beta - 360 : beta;

  // Filter event based the time elapsed and the angle deltas since the last
  // event.
  base::TimeTicks now = base::TimeTicks::Now();
  if (!last_event_time_ ||
      (now - *last_event_time_).InSecondsF() >
          1.0 / ORIENTATION_EVENT_MIN_FREQUENCY_HZ ||
      fabs(alpha - last_event_alpha_) >
          ORIENTATION_EVENT_DELTA_THRESHOLD_DEGREES ||
      fabs(beta - last_event_beta_) >
          ORIENTATION_EVENT_DELTA_THRESHOLD_DEGREES ||
      fabs(gamma - last_event_gamma_) >
          ORIENTATION_EVENT_DELTA_THRESHOLD_DEGREES) {
    DeviceOrientationEventInit init;
    init.set_absolute(false);
    init.set_alpha(alpha);
    init.set_beta(beta);
    init.set_gamma(gamma);

    target->DispatchEvent(
        new DeviceOrientationEvent("deviceorientation", init));
    last_event_time_ = now;
    last_event_alpha_ = alpha;
    last_event_beta_ = beta;
    last_event_gamma_ = gamma;
  }
}

}  // namespace dom
}  // namespace cobalt
