/*
 *  Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
 *
 *  Use of this source code is governed by a BSD-style license
 *  that can be found in the LICENSE file in the root of the source
 *  tree. An additional intellectual property rights grant can be found
 *  in the file PATENTS.  All contributing project authors may
 *  be found in the AUTHORS file in the root of the source tree.
 */

#include "webrtc/modules/audio_coding/neteq/audio_multi_vector.h"

#include <assert.h>

#include <algorithm>

#include "webrtc/typedefs.h"

namespace webrtc {

AudioMultiVector::AudioMultiVector(size_t N) {
  assert(N > 0);
  if (N < 1) N = 1;
  for (size_t n = 0; n < N; ++n) {
    channels_.push_back(new AudioVector);
  }
  num_channels_ = N;
}

AudioMultiVector::AudioMultiVector(size_t N, size_t initial_size) {
  assert(N > 0);
  if (N < 1) N = 1;
  for (size_t n = 0; n < N; ++n) {
    channels_.push_back(new AudioVector(initial_size));
  }
  num_channels_ = N;
}

AudioMultiVector::~AudioMultiVector() {
  std::vector<AudioVector*>::iterator it = channels_.begin();
  while (it != channels_.end()) {
    delete (*it);
    ++it;
  }
}

void AudioMultiVector::Clear() {
  for (size_t i = 0; i < num_channels_; ++i) {
    channels_[i]->Clear();
  }
}

void AudioMultiVector::Zeros(size_t length) {
  for (size_t i = 0; i < num_channels_; ++i) {
    channels_[i]->Clear();
    channels_[i]->Extend(length);
  }
}

void AudioMultiVector::CopyTo(AudioMultiVector* copy_to) const {
  if (copy_to) {
    for (size_t i = 0; i < num_channels_; ++i) {
      channels_[i]->CopyTo(&(*copy_to)[i]);
    }
  }
}

void AudioMultiVector::PushBackInterleaved(const int16_t* append_this,
                                           size_t length) {
  assert(length % num_channels_ == 0);
  if (num_channels_ == 1) {
    // Special case to avoid extra allocation and data shuffling.
    channels_[0]->PushBack(append_this, length);
    return;
  }
  size_t length_per_channel = length / num_channels_;
  int16_t* temp_array = new int16_t[length_per_channel];  // Temporary storage.
  for (size_t channel = 0; channel < num_channels_; ++channel) {
    // Copy elements to |temp_array|.
    // Set |source_ptr| to first element of this channel.
    const int16_t* source_ptr = &append_this[channel];
    for (size_t i = 0; i < length_per_channel; ++i) {
      temp_array[i] = *source_ptr;
      source_ptr += num_channels_;  // Jump to next element of this channel.
    }
    channels_[channel]->PushBack(temp_array, length_per_channel);
  }
  delete [] temp_array;
}

void AudioMultiVector::PushBack(const AudioMultiVector& append_this) {
  assert(num_channels_ == append_this.num_channels_);
  if (num_channels_ == append_this.num_channels_) {
    for (size_t i = 0; i < num_channels_; ++i) {
      channels_[i]->PushBack(append_this[i]);
    }
  }
}

void AudioMultiVector::PushBackFromIndex(const AudioMultiVector& append_this,
                                         size_t index) {
  assert(index < append_this.Size());
  index = std::min(index, append_this.Size() - 1);
  size_t length = append_this.Size() - index;
  assert(num_channels_ == append_this.num_channels_);
  if (num_channels_ == append_this.num_channels_) {
    for (size_t i = 0; i < num_channels_; ++i) {
      channels_[i]->PushBack(&append_this[i][index], length);
    }
  }
}

void AudioMultiVector::PopFront(size_t length) {
  for (size_t i = 0; i < num_channels_; ++i) {
    channels_[i]->PopFront(length);
  }
}

void AudioMultiVector::PopBack(size_t length) {
  for (size_t i = 0; i < num_channels_; ++i) {
    channels_[i]->PopBack(length);
  }
}

size_t AudioMultiVector::ReadInterleaved(size_t length,
                                         int16_t* destination) const {
  return ReadInterleavedFromIndex(0, length, destination);
}

size_t AudioMultiVector::ReadInterleavedFromIndex(size_t start_index,
                                                  size_t length,
                                                  int16_t* destination) const {
  if (!destination) {
    return 0;
  }
  size_t index = 0;  // Number of elements written to |destination| so far.
  assert(start_index <= Size());
  start_index = std::min(start_index, Size());
  if (length + start_index > Size()) {
    length = Size() - start_index;
  }
  if (num_channels_ == 1) {
    // Special case to avoid the nested for loop below.
    memcpy(destination, &(*this)[0][start_index], length * sizeof(int16_t));
    return length;
  }
  for (size_t i = 0; i < length; ++i) {
    for (size_t channel = 0; channel < num_channels_; ++channel) {
      destination[index] = (*this)[channel][i + start_index];
      ++index;
    }
  }
  return index;
}

size_t AudioMultiVector::ReadInterleavedFromEnd(size_t length,
                                                int16_t* destination) const {
  length = std::min(length, Size());  // Cannot read more than Size() elements.
  return ReadInterleavedFromIndex(Size() - length, length, destination);
}

void AudioMultiVector::OverwriteAt(const AudioMultiVector& insert_this,
                                   size_t length,
                                   size_t position) {
  assert(num_channels_ == insert_this.num_channels_);
  // Cap |length| at the length of |insert_this|.
  assert(length <= insert_this.Size());
  length = std::min(length, insert_this.Size());
  if (num_channels_ == insert_this.num_channels_) {
    for (size_t i = 0; i < num_channels_; ++i) {
      channels_[i]->OverwriteAt(&insert_this[i][0], length, position);
    }
  }
}

void AudioMultiVector::CrossFade(const AudioMultiVector& append_this,
                                 size_t fade_length) {
  assert(num_channels_ == append_this.num_channels_);
  if (num_channels_ == append_this.num_channels_) {
    for (size_t i = 0; i < num_channels_; ++i) {
      channels_[i]->CrossFade(append_this[i], fade_length);
    }
  }
}

size_t AudioMultiVector::Channels() const {
  return num_channels_;
}

size_t AudioMultiVector::Size() const {
  assert(channels_[0]);
  return channels_[0]->Size();
}

void AudioMultiVector::AssertSize(size_t required_size) {
  if (Size() < required_size) {
    size_t extend_length = required_size - Size();
    for (size_t channel = 0; channel < num_channels_; ++channel) {
      channels_[channel]->Extend(extend_length);
    }
  }
}

bool AudioMultiVector::Empty() const {
  assert(channels_[0]);
  return channels_[0]->Empty();
}

void AudioMultiVector::CopyChannel(size_t from_channel, size_t to_channel) {
  assert(from_channel < num_channels_);
  assert(to_channel < num_channels_);
  channels_[from_channel]->CopyTo(channels_[to_channel]);
}

const AudioVector& AudioMultiVector::operator[](size_t index) const {
  return *(channels_[index]);
}

AudioVector& AudioMultiVector::operator[](size_t index) {
  return *(channels_[index]);
}

}  // namespace webrtc
