// Copyright 2015 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/audio/audio_context.h"

#include <memory>

#include "base/callback.h"
#include "cobalt/base/polymorphic_downcast.h"
#include "cobalt/dom/dom_settings.h"

namespace cobalt {
namespace audio {

AudioContext::AudioContext(script::EnvironmentSettings* settings)
    : dom::EventTarget(settings),
      global_environment_(
          base::polymorphic_downcast<dom::DOMSettings*>(settings)
              ->global_environment()),
      ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          weak_this_(weak_ptr_factory_.GetWeakPtr())),
      sample_rate_(
          static_cast<float>(SbAudioSinkGetNearestSupportedSampleFrequency(
              kStandardOutputSampleRate))),
      current_time_(0.0f),
      audio_lock_(new AudioLock()),
      ALLOW_THIS_IN_INITIALIZER_LIST(
          destination_(new AudioDestinationNode(settings, this))),
      next_callback_id_(0),
      main_message_loop_(base::MessageLoop::current()->task_runner()) {
  DCHECK(main_message_loop_);
}

AudioContext::~AudioContext() {
  DCHECK(main_message_loop_->BelongsToCurrentThread());

  // Before releasing any |pending_decode_callbacks_|, stop audio decoder
  // explicitly to ensure that all the decoding works are done.
  audio_decoder_.Stop();

  // It is possible that the callbacks in |pending_decode_callbacks_| have not
  // been called when destroying AudioContext.
  for (DecodeCallbacks::iterator it = pending_decode_callbacks_.begin();
       it != pending_decode_callbacks_.end(); ++it) {
    delete it->second;
  }
}

scoped_refptr<AudioBuffer> AudioContext::CreateBuffer(uint32 num_of_channels,
                                                      uint32 length,
                                                      float sample_rate) {
  DCHECK(main_message_loop_->BelongsToCurrentThread());

  return scoped_refptr<AudioBuffer>(new AudioBuffer(
      sample_rate, std::unique_ptr<AudioBus>(new AudioBus(
                       num_of_channels, length, GetPreferredOutputSampleType(),
                       kStorageTypeInterleaved))));
}

scoped_refptr<AudioBufferSourceNode> AudioContext::CreateBufferSource(
    script::EnvironmentSettings* settings) {
  DCHECK(main_message_loop_->BelongsToCurrentThread());

  return scoped_refptr<AudioBufferSourceNode>(
      new AudioBufferSourceNode(settings, this));
}

void AudioContext::PreventGarbageCollection() {
  prevent_gc_until_playback_complete_.reset(
      new script::GlobalEnvironment::ScopedPreventGarbageCollection(
          global_environment_, this));
}

void AudioContext::AllowGarbageCollection() {
  prevent_gc_until_playback_complete_.reset();
}

void AudioContext::AddBufferSource(
    const scoped_refptr<AudioBufferSourceNode>& buffer_source) {
  buffer_sources_.insert(buffer_source);
}

void AudioContext::RemoveBufferSource(
    const scoped_refptr<AudioBufferSourceNode>& buffer_source) {
  if (buffer_sources_.find(buffer_source) != buffer_sources_.end()) {
    buffer_sources_.erase(buffer_source);
  }
}

void AudioContext::TraceMembers(script::Tracer* tracer) {
  dom::EventTarget::TraceMembers(tracer);

  tracer->Trace(destination_.get());
  for (const auto& source : buffer_sources_) {
    tracer->Trace(source);
  }
}

void AudioContext::DecodeAudioData(
    script::EnvironmentSettings* settings,
    const script::Handle<script::ArrayBuffer>& audio_data,
    const DecodeSuccessCallbackArg& success_handler) {
  DCHECK(main_message_loop_->BelongsToCurrentThread());

  std::unique_ptr<DecodeCallbackInfo> info(
      new DecodeCallbackInfo(settings, audio_data, this, success_handler));
  DecodeAudioDataInternal(std::move(info));
}

void AudioContext::DecodeAudioData(
    script::EnvironmentSettings* settings,
    const script::Handle<script::ArrayBuffer>& audio_data,
    const DecodeSuccessCallbackArg& success_handler,
    const DecodeErrorCallbackArg& error_handler) {
  DCHECK(main_message_loop_->BelongsToCurrentThread());

  std::unique_ptr<DecodeCallbackInfo> info(new DecodeCallbackInfo(
      settings, audio_data, this, success_handler, error_handler));
  DecodeAudioDataInternal(std::move(info));
}

void AudioContext::DecodeAudioDataInternal(
    std::unique_ptr<DecodeCallbackInfo> info) {
  DCHECK(main_message_loop_->BelongsToCurrentThread());

  const int callback_id = next_callback_id_++;
  CHECK(pending_decode_callbacks_.find(callback_id) ==
        pending_decode_callbacks_.end());
  script::Handle<script::ArrayBuffer> audio_data =
      script::Handle<script::ArrayBuffer>(info->audio_data_reference);
  pending_decode_callbacks_[callback_id] = info.release();

  AsyncAudioDecoder::DecodeFinishCallback decode_callback = base::Bind(
      &AudioContext::DecodeFinish, base::Unretained(this), callback_id);
  audio_decoder_.AsyncDecode(static_cast<const uint8*>(audio_data->Data()),
                             audio_data->ByteLength(), decode_callback);
}

// Success callback and error callback should be scheduled to run on the main
// thread's event loop.
void AudioContext::DecodeFinish(int callback_id, float sample_rate,
                                std::unique_ptr<AudioBus> audio_bus) {
  if (!main_message_loop_->BelongsToCurrentThread()) {
    main_message_loop_->PostTask(
        FROM_HERE,
        base::Bind(&AudioContext::DecodeFinish, weak_this_, callback_id,
                   sample_rate, base::Passed(&audio_bus)));
    return;
  }

  DecodeCallbacks::iterator info_iterator =
      pending_decode_callbacks_.find(callback_id);
  DCHECK(info_iterator != pending_decode_callbacks_.end());

  std::unique_ptr<DecodeCallbackInfo> info(info_iterator->second);
  pending_decode_callbacks_.erase(info_iterator);

  if (audio_bus) {
    const scoped_refptr<AudioBuffer>& audio_buffer =
        new AudioBuffer(sample_rate, std::move(audio_bus));
    info->success_callback.value().Run(audio_buffer);
  } else if (info->error_callback) {
    info->error_callback.value().value().Run();
  }
}

}  // namespace audio
}  // namespace cobalt
