/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 *
 * 1.  Redistributions of source code must retain the above copyright
 *     notice, this list of conditions and the following disclaimer.
 * 2.  Redistributions in binary form must reproduce the above copyright
 *     notice, this list of conditions and the following disclaimer in the
 *     documentation and/or other materials provided with the distribution.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#include "third_party/blink/renderer/modules/webaudio/audio_listener.h"
#include "third_party/blink/renderer/modules/webaudio/panner_node.h"
#include "third_party/blink/renderer/platform/audio/audio_bus.h"
#include "third_party/blink/renderer/platform/audio/audio_utilities.h"
#include "third_party/blink/renderer/platform/audio/hrtf_database_loader.h"

namespace blink {

AudioListener::AudioListener(BaseAudioContext& context)
    : position_x_(
          AudioParam::Create(context,
                             kParamTypeAudioListenerPositionX,
                             0.0,
                             AudioParamHandler::AutomationRate::kAudio,
                             AudioParamHandler::AutomationRateMode::kVariable)),
      position_y_(
          AudioParam::Create(context,
                             kParamTypeAudioListenerPositionY,
                             0.0,
                             AudioParamHandler::AutomationRate::kAudio,
                             AudioParamHandler::AutomationRateMode::kVariable)),
      position_z_(
          AudioParam::Create(context,
                             kParamTypeAudioListenerPositionZ,
                             0.0,
                             AudioParamHandler::AutomationRate::kAudio,
                             AudioParamHandler::AutomationRateMode::kVariable)),
      forward_x_(
          AudioParam::Create(context,
                             kParamTypeAudioListenerForwardX,
                             0.0,
                             AudioParamHandler::AutomationRate::kAudio,
                             AudioParamHandler::AutomationRateMode::kVariable)),
      forward_y_(
          AudioParam::Create(context,
                             kParamTypeAudioListenerForwardY,
                             0.0,
                             AudioParamHandler::AutomationRate::kAudio,
                             AudioParamHandler::AutomationRateMode::kVariable)),
      forward_z_(
          AudioParam::Create(context,
                             kParamTypeAudioListenerForwardZ,
                             -1.0,
                             AudioParamHandler::AutomationRate::kAudio,
                             AudioParamHandler::AutomationRateMode::kVariable)),
      up_x_(
          AudioParam::Create(context,
                             kParamTypeAudioListenerUpX,
                             0.0,
                             AudioParamHandler::AutomationRate::kAudio,
                             AudioParamHandler::AutomationRateMode::kVariable)),
      up_y_(
          AudioParam::Create(context,
                             kParamTypeAudioListenerUpY,
                             1.0,
                             AudioParamHandler::AutomationRate::kAudio,
                             AudioParamHandler::AutomationRateMode::kVariable)),
      up_z_(
          AudioParam::Create(context,
                             kParamTypeAudioListenerUpZ,
                             0.0,
                             AudioParamHandler::AutomationRate::kAudio,
                             AudioParamHandler::AutomationRateMode::kVariable)),
      last_update_time_(-1),
      is_listener_dirty_(false),
      position_x_values_(audio_utilities::kRenderQuantumFrames),
      position_y_values_(audio_utilities::kRenderQuantumFrames),
      position_z_values_(audio_utilities::kRenderQuantumFrames),
      forward_x_values_(audio_utilities::kRenderQuantumFrames),
      forward_y_values_(audio_utilities::kRenderQuantumFrames),
      forward_z_values_(audio_utilities::kRenderQuantumFrames),
      up_x_values_(audio_utilities::kRenderQuantumFrames),
      up_y_values_(audio_utilities::kRenderQuantumFrames),
      up_z_values_(audio_utilities::kRenderQuantumFrames) {
  // Initialize the cached values with the current values.  Thus, we don't need
  // to notify any panners because we haved moved.
  last_position_ = GetPosition();
  last_forward_ = Orientation();
  last_up_ = UpVector();
}

AudioListener::~AudioListener() = default;

void AudioListener::Trace(blink::Visitor* visitor) {
  visitor->Trace(position_x_);
  visitor->Trace(position_y_);
  visitor->Trace(position_z_);

  visitor->Trace(forward_x_);
  visitor->Trace(forward_y_);
  visitor->Trace(forward_z_);

  visitor->Trace(up_x_);
  visitor->Trace(up_y_);
  visitor->Trace(up_z_);

  ScriptWrappable::Trace(visitor);
}

void AudioListener::AddPanner(PannerHandler& panner) {
  DCHECK(IsMainThread());
  panners_.insert(&panner);
}

void AudioListener::RemovePanner(PannerHandler& panner) {
  DCHECK(IsMainThread());
  DCHECK(panners_.Contains(&panner));
  panners_.erase(&panner);
}

bool AudioListener::HasSampleAccurateValues() const {
  return positionX()->Handler().HasSampleAccurateValues() ||
         positionY()->Handler().HasSampleAccurateValues() ||
         positionZ()->Handler().HasSampleAccurateValues() ||
         forwardX()->Handler().HasSampleAccurateValues() ||
         forwardY()->Handler().HasSampleAccurateValues() ||
         forwardZ()->Handler().HasSampleAccurateValues() ||
         upX()->Handler().HasSampleAccurateValues() ||
         upY()->Handler().HasSampleAccurateValues() ||
         upZ()->Handler().HasSampleAccurateValues();
}

void AudioListener::UpdateValuesIfNeeded(uint32_t frames_to_process) {
  double current_time =
      positionX()->Handler().DestinationHandler().CurrentTime();
  if (last_update_time_ != current_time) {
    // Time has changed. Update all of the automation values now.
    last_update_time_ = current_time;

    bool sizes_are_good = frames_to_process <= position_x_values_.size() &&
                          frames_to_process <= position_y_values_.size() &&
                          frames_to_process <= position_z_values_.size() &&
                          frames_to_process <= forward_x_values_.size() &&
                          frames_to_process <= forward_y_values_.size() &&
                          frames_to_process <= forward_z_values_.size() &&
                          frames_to_process <= up_x_values_.size() &&
                          frames_to_process <= up_y_values_.size() &&
                          frames_to_process <= up_z_values_.size();

    DCHECK(sizes_are_good);
    if (!sizes_are_good)
      return;

    positionX()->Handler().CalculateSampleAccurateValues(
        position_x_values_.Data(), frames_to_process);
    positionY()->Handler().CalculateSampleAccurateValues(
        position_y_values_.Data(), frames_to_process);
    positionZ()->Handler().CalculateSampleAccurateValues(
        position_z_values_.Data(), frames_to_process);

    forwardX()->Handler().CalculateSampleAccurateValues(
        forward_x_values_.Data(), frames_to_process);
    forwardY()->Handler().CalculateSampleAccurateValues(
        forward_y_values_.Data(), frames_to_process);
    forwardZ()->Handler().CalculateSampleAccurateValues(
        forward_z_values_.Data(), frames_to_process);

    upX()->Handler().CalculateSampleAccurateValues(up_x_values_.Data(),
                                                   frames_to_process);
    upY()->Handler().CalculateSampleAccurateValues(up_y_values_.Data(),
                                                   frames_to_process);
    upZ()->Handler().CalculateSampleAccurateValues(up_z_values_.Data(),
                                                   frames_to_process);
  }
}

const float* AudioListener::GetPositionXValues(uint32_t frames_to_process) {
  UpdateValuesIfNeeded(frames_to_process);
  return position_x_values_.Data();
}

const float* AudioListener::GetPositionYValues(uint32_t frames_to_process) {
  UpdateValuesIfNeeded(frames_to_process);
  return position_y_values_.Data();
}

const float* AudioListener::GetPositionZValues(uint32_t frames_to_process) {
  UpdateValuesIfNeeded(frames_to_process);
  return position_z_values_.Data();
}

const float* AudioListener::GetForwardXValues(uint32_t frames_to_process) {
  UpdateValuesIfNeeded(frames_to_process);
  return forward_x_values_.Data();
}

const float* AudioListener::GetForwardYValues(uint32_t frames_to_process) {
  UpdateValuesIfNeeded(frames_to_process);
  return forward_y_values_.Data();
}

const float* AudioListener::GetForwardZValues(uint32_t frames_to_process) {
  UpdateValuesIfNeeded(frames_to_process);
  return forward_z_values_.Data();
}

const float* AudioListener::GetUpXValues(uint32_t frames_to_process) {
  UpdateValuesIfNeeded(frames_to_process);
  return up_x_values_.Data();
}

const float* AudioListener::GetUpYValues(uint32_t frames_to_process) {
  UpdateValuesIfNeeded(frames_to_process);
  return up_y_values_.Data();
}

const float* AudioListener::GetUpZValues(uint32_t frames_to_process) {
  UpdateValuesIfNeeded(frames_to_process);
  return up_z_values_.Data();
}

void AudioListener::UpdateState() {
  // This must be called from the audio thread in pre or post render phase of
  // the graph processing.  (AudioListener doesn't have access to the context
  // to check for the audio thread.)
  DCHECK(!IsMainThread());

  MutexTryLocker try_locker(listener_lock_);
  if (try_locker.Locked()) {
    FloatPoint3D current_position = GetPosition();
    FloatPoint3D current_forward = Orientation();
    FloatPoint3D current_up = UpVector();

    is_listener_dirty_ = current_position != last_position_ ||
                         current_forward != last_forward_ ||
                         current_up != last_up_;

    if (is_listener_dirty_) {
      last_position_ = current_position;
      last_forward_ = current_forward;
      last_up_ = current_up;
    }
  } else {
    // Main thread must be updating the position, forward, or up vector;
    // just assume the listener is dirty.  At worst, we'll do a little more
    // work than necessary for one rendering quantum.
    is_listener_dirty_ = true;
  }
}

void AudioListener::CreateAndLoadHRTFDatabaseLoader(float sample_rate) {
  DCHECK(IsMainThread());

  if (!hrtf_database_loader_)
    hrtf_database_loader_ =
        HRTFDatabaseLoader::CreateAndLoadAsynchronouslyIfNecessary(sample_rate);
}

bool AudioListener::IsHRTFDatabaseLoaded() {
  return hrtf_database_loader_ && hrtf_database_loader_->IsLoaded();
}

void AudioListener::WaitForHRTFDatabaseLoaderThreadCompletion() {
  if (hrtf_database_loader_)
    hrtf_database_loader_->WaitForLoaderThreadCompletion();
}

void AudioListener::MarkPannersAsDirty(unsigned type) {
  DCHECK(IsMainThread());
  for (PannerHandler* panner : panners_)
    panner->MarkPannerAsDirty(type);
}

void AudioListener::setPosition(const FloatPoint3D& position,
                                ExceptionState& exceptionState) {
  DCHECK(IsMainThread());

  // This synchronizes with panner's process().
  MutexLocker listener_locker(listener_lock_);

  double now = position_x_->Context()->currentTime();

  position_x_->setValueAtTime(position.X(), now, exceptionState);
  position_y_->setValueAtTime(position.Y(), now, exceptionState);
  position_z_->setValueAtTime(position.Z(), now, exceptionState);

  MarkPannersAsDirty(PannerHandler::kAzimuthElevationDirty |
                     PannerHandler::kDistanceConeGainDirty);
}

void AudioListener::setOrientation(const FloatPoint3D& orientation,
                                   ExceptionState& exceptionState) {
  DCHECK(IsMainThread());

  // This synchronizes with panner's process().
  MutexLocker listener_locker(listener_lock_);

  double now = forward_x_->Context()->currentTime();

  forward_x_->setValueAtTime(orientation.X(), now, exceptionState);
  forward_y_->setValueAtTime(orientation.Y(), now, exceptionState);
  forward_z_->setValueAtTime(orientation.Z(), now, exceptionState);

  MarkPannersAsDirty(PannerHandler::kAzimuthElevationDirty);
}

void AudioListener::SetUpVector(const FloatPoint3D& up_vector,
                                ExceptionState& exceptionState) {
  DCHECK(IsMainThread());

  // This synchronizes with panner's process().
  MutexLocker listener_locker(listener_lock_);

  double now = up_x_->Context()->currentTime();

  up_x_->setValueAtTime(up_vector.X(), now, exceptionState);
  up_y_->setValueAtTime(up_vector.Y(), now, exceptionState);
  up_z_->setValueAtTime(up_vector.Z(), now, exceptionState);

  MarkPannersAsDirty(PannerHandler::kAzimuthElevationDirty);
}

}  // namespace blink
