/*
 *  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.
 */

#ifndef WEBRTC_MODULES_AUDIO_CODING_NETEQ4_AUDIO_VECTOR_H_
#define WEBRTC_MODULES_AUDIO_CODING_NETEQ4_AUDIO_VECTOR_H_

#include <string.h>  // Access to size_t.

#include "webrtc/base/constructormagic.h"
#include "webrtc/system_wrappers/interface/scoped_ptr.h"
#include "webrtc/typedefs.h"

namespace webrtc {

class AudioVector {
 public:
  // Creates an empty AudioVector.
  AudioVector()
      : array_(new int16_t[kDefaultInitialSize]),
        first_free_ix_(0),
        capacity_(kDefaultInitialSize) {}

  // Creates an AudioVector with an initial size.
  explicit AudioVector(size_t initial_size)
      : array_(new int16_t[initial_size]),
        first_free_ix_(initial_size),
        capacity_(initial_size) {
    memset(array_.get(), 0, initial_size * sizeof(int16_t));
  }

  virtual ~AudioVector() {}

  // Deletes all values and make the vector empty.
  virtual void Clear();

  // Copies all values from this vector to |copy_to|. Any contents in |copy_to|
  // are deleted before the copy operation. After the operation is done,
  // |copy_to| will be an exact replica of this object.
  virtual void CopyFrom(AudioVector* copy_to) const;

  // Prepends the contents of AudioVector |prepend_this| to this object. The
  // length of this object is increased with the length of |prepend_this|.
  virtual void PushFront(const AudioVector& prepend_this);

  // Same as above, but with an array |prepend_this| with |length| elements as
  // source.
  virtual void PushFront(const int16_t* prepend_this, size_t length);

  // Same as PushFront but will append to the end of this object.
  virtual void PushBack(const AudioVector& append_this);

  // Same as PushFront but will append to the end of this object.
  virtual void PushBack(const int16_t* append_this, size_t length);

  // Removes |length| elements from the beginning of this object.
  virtual void PopFront(size_t length);

  // Removes |length| elements from the end of this object.
  virtual void PopBack(size_t length);

  // Extends this object with |extra_length| elements at the end. The new
  // elements are initialized to zero.
  virtual void Extend(size_t extra_length);

  // Inserts |length| elements taken from the array |insert_this| and insert
  // them at |position|. The length of the AudioVector is increased by |length|.
  // |position| = 0 means that the new values are prepended to the vector.
  // |position| = Size() means that the new values are appended to the vector.
  virtual void InsertAt(const int16_t* insert_this, size_t length,
                        size_t position);

  // Like InsertAt, but inserts |length| zero elements at |position|.
  virtual void InsertZerosAt(size_t length, size_t position);

  // Overwrites |length| elements of this AudioVector with values taken from the
  // array |insert_this|, starting at |position|. The definition of |position|
  // is the same as for InsertAt(). If |length| and |position| are selected
  // such that the new data extends beyond the end of the current AudioVector,
  // the vector is extended to accommodate the new data.
  virtual void OverwriteAt(const int16_t* insert_this,
                           size_t length,
                           size_t position);

  // Appends |append_this| to the end of the current vector. Lets the two
  // vectors overlap by |fade_length| samples, and cross-fade linearly in this
  // region.
  virtual void CrossFade(const AudioVector& append_this, size_t fade_length);

  // Returns the number of elements in this AudioVector.
  virtual size_t Size() const { return first_free_ix_; }

  // Returns true if this AudioVector is empty.
  virtual bool Empty() const { return (first_free_ix_ == 0); }

  // Accesses and modifies an element of AudioVector.
  const int16_t& operator[](size_t index) const;
  int16_t& operator[](size_t index);

 private:
  static const size_t kDefaultInitialSize = 10;

  void Reserve(size_t n);

  scoped_ptr<int16_t[]> array_;
  size_t first_free_ix_;  // The first index after the last sample in array_.
                          // Note that this index may point outside of array_.
  size_t capacity_;  // Allocated number of samples in the array.

  DISALLOW_COPY_AND_ASSIGN(AudioVector);
};

}  // namespace webrtc
#endif  // WEBRTC_MODULES_AUDIO_CODING_NETEQ4_AUDIO_VECTOR_H_
