/*
 * Copyright 2015 Google Inc. 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_node.h"

#include "cobalt/audio/audio_context.h"
#include "cobalt/dom/dom_exception.h"

namespace cobalt {
namespace audio {

AudioNode::AudioNode(AudioContext* context)
    : audio_context_(context),
      audio_lock_(context->audio_lock()),
      channel_count_(2),
      channel_count_mode_(AudioNode::kMax),
      channel_interpretation_(AudioNode::kSpeakers) {}

AudioNode::~AudioNode() {
  AudioLock::AutoLock lock(audio_lock());

  RemoveAllInputs();
  RemoveAllOutputs();
}

void AudioNode::set_channel_count(uint32 channel_count,
                                  script::ExceptionState* exception_state) {
  AudioLock::AutoLock lock(audio_lock());

  // If this value is set to zero, the implementation MUST throw a
  // NOT_SUPPORTED_ERR exception.
  if (channel_count == 0) {
    dom::DOMException::Raise(dom::DOMException::kNotSupportedErr,
                             exception_state);
    return;
  }

  // TODO: Check if this AudioNode is destination when setting the
  // channel count. If it is destination, channel count may be set to any
  // non-zero value less than or equal to max channel count of the destination.
  // An INDEX_SIZE_ERR exception MUST be thrown if this value is not within the
  // valid range.
  channel_count_ = channel_count;
}

void AudioNode::set_channel_count_mode(
    const ChannelCountMode& channel_count_mode) {
  AudioLock::AutoLock lock(audio_lock());

  channel_count_mode_ = channel_count_mode;
}

void AudioNode::set_channel_interpretation(
    const ChannelInterpretation& channel_interpretation) {
  AudioLock::AutoLock lock(audio_lock());

  channel_interpretation_ = channel_interpretation;
}

void AudioNode::Connect(const scoped_refptr<AudioNode>& destination,
                        uint32 output, uint32 input,
                        script::ExceptionState* exception_state) {
  AudioLock::AutoLock lock(audio_lock());

  // The destination parameter is the AudioNode to connect to.
  if (!destination) {
    dom::DOMException::Raise(dom::DOMException::kSyntaxErr, exception_state);
    return;
  }
  // The output parameter is an index describing which output of the AudioNode
  // from which to connect. If this paremeter is out-of-bound, an INDEX_SIZE_ERR
  // exception MUST be thrown.
  if (output >= number_of_outputs()) {
    dom::DOMException::Raise(dom::DOMException::kIndexSizeErr, exception_state);
    return;
  }
  // The input parameter is an index describing which input of the destination
  // AudioNode to connect to. If this parameter is out-of-bound, an
  // INDEX_SIZE_ERR exception MUST be thrown.
  if (input >= destination->number_of_inputs()) {
    dom::DOMException::Raise(dom::DOMException::kIndexSizeErr, exception_state);
    return;
  }

  // TODO: Detect if there is a cycle when connecting an AudioNode to
  // another AudioNode. A cycle is allowed only if there is at least one
  // DelayNode in the cycle or a NOT_SUPPORTED_ERR exception MUST be thrown.
  AudioNodeInput* input_node = destination->inputs_[input];
  AudioNodeOutput* output_node = outputs_[output];

  DCHECK(input_node);
  DCHECK(output_node);

  input_node->Connect(output_node);
}

void AudioNode::Disconnect(uint32 output,
                           script::ExceptionState* exception_state) {
  AudioLock::AutoLock lock(audio_lock());

  // The output parameter is an index describing which output of the AudioNode
  // to disconnect. If the output parameter is out-of-bounds, an INDEX_SIZE_ERR
  // exception MUST be thrown.
  if (output >= number_of_outputs()) {
    dom::DOMException::Raise(dom::DOMException::kIndexSizeErr, exception_state);
    return;
  }

  scoped_refptr<AudioNodeOutput> output_node = outputs_[output];

  DCHECK(output_node);
  output_node->DisconnectAll();
}

void AudioNode::AddInput(const scoped_refptr<AudioNodeInput>& input) {
  audio_lock()->AssertLocked();

  DCHECK(input);

  inputs_.push_back(input);
}

void AudioNode::AddOutput(const scoped_refptr<AudioNodeOutput>& output) {
  audio_lock()->AssertLocked();

  DCHECK(output);

  outputs_.push_back(output);
}

void AudioNode::RemoveAllInputs() {
  audio_lock()->AssertLocked();

  while (!inputs_.empty()) {
    scoped_refptr<AudioNodeInput> input = inputs_.back();
    input->DisconnectAll();
    inputs_.pop_back();
  }
}

void AudioNode::RemoveAllOutputs() {
  audio_lock()->AssertLocked();

  while (!outputs_.empty()) {
    scoped_refptr<AudioNodeOutput> output = outputs_.back();
    output->DisconnectAll();
    outputs_.pop_back();
  }
}

AudioNodeInput* AudioNode::Input(int32 index) const {
  audio_lock()->AssertLocked();

  size_t input_index = static_cast<size_t>(index);
  if (input_index < inputs_.size()) {
    return inputs_[input_index].get();
  }
  return NULL;
}

AudioNodeOutput* AudioNode::Output(int32 index) const {
  audio_lock()->AssertLocked();

  size_t output_index = static_cast<size_t>(index);
  if (output_index < outputs_.size()) {
    return outputs_[output_index].get();
  }
  return NULL;
}

}  // namespace audio
}  // namespace cobalt
