/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * 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 "ring_buffer.h"

#include <algorithm>

#include "integral_types.h"

namespace video_editing {

void RingBuffer::Init(int size, int num_channels, int num_readers) {
  size_ = size;
  num_channels_ = num_channels;
  num_readers_ = num_readers;
  temp_read_buffer_size_ = 1024;
  initialized_ = true;
  Reset();
}

RingBuffer::RingBuffer()
    : initialized_(false), samples_(NULL),
      num_readers_(0), temp_read_buffer_(NULL) {
}

RingBuffer::~RingBuffer() {
  delete[] samples_;
  delete[] temp_read_buffer_;
}

void RingBuffer::Reset() {
  delete[] samples_;
  samples_ = new float[size_ * num_channels_];
  memset(samples_, 0,
         size_ * num_channels_ * sizeof(samples_[0]));

  temp_read_buffer_size_ = 1024;
  delete[] temp_read_buffer_;
  temp_read_buffer_ = new float[temp_read_buffer_size_ * num_channels_];
  memset(temp_read_buffer_, 0,
         temp_read_buffer_size_ * num_channels_ * sizeof(samples_[0]));
  readers_.clear();
  for (int i = 0; i < num_readers_; ++i) {
    readers_.push_back(0LL);
  }
  head_logical_ = 0LL;
  head_ = 0;
}

int RingBuffer::available(int reader) const {
  return head_logical_ - readers_[reader];
}

int RingBuffer::overhead() const {
  int64 tail = GetTail();
  return tail + size_ - head_logical_;
}

int64 RingBuffer::GetTail() const {
  return *std::min_element(readers_.begin(), readers_.end());
}

int64 RingBuffer::Tell(int reader) const {
  return readers_[reader];
}

void RingBuffer::Seek(int reader, int64 position) {
  readers_[reader] = position;
}

void RingBuffer::Write(const float* samples, int num_frames) {
  if (!num_frames) {
    return;
  }
  if (head_ + num_frames <= size_) {
    memcpy(samples_ + head_ * num_channels_, samples,
           num_frames * num_channels_ * sizeof(samples[0]));
    head_ += num_frames;
  } else {
    int overhead = size_ - head_;
    memcpy(samples_ + head_ * num_channels_, samples,
           num_channels_ * overhead * sizeof(samples[0]));
    head_ = num_frames - overhead;
    memcpy(samples_, samples + overhead * num_channels_,
           num_channels_ * head_ * sizeof(samples[0]));
  }
  head_logical_ += num_frames;
}

void RingBuffer::Copy(int reader, float* destination, int num_frames) const {
  int pos = Tell(reader) % size_;
  if (pos + num_frames <= size_) {
    memcpy(destination, samples_ + pos * num_channels_,
           num_channels_ * num_frames * sizeof(destination[0]));
  } else {
    int wrapped = size_ - pos;
    memcpy(destination, samples_ + pos * num_channels_,
           num_channels_ * wrapped * sizeof(destination[0]));
    int remaining = num_frames - wrapped;
    memcpy(destination + wrapped * num_channels_, samples_,
           num_channels_ * remaining * sizeof(destination[0]));
  }
}

float* RingBuffer::GetPointer(int reader, int num_frames) {
  int pos = Tell(reader) % size_;
  if (pos + num_frames <= size_) {
    return samples_ + pos * num_channels_;
  } else {
    if (num_frames > temp_read_buffer_size_) {
      temp_read_buffer_size_ = num_frames;
      delete[] temp_read_buffer_;
      temp_read_buffer_ =
          new float[temp_read_buffer_size_ * num_channels_];  // NOLINT
    }
    Copy(reader, temp_read_buffer_, num_frames);
    return temp_read_buffer_;
  }
}

void RingBuffer::MergeBack(int reader, const float* source, int num_frames) {
  // If the source pointer is not the temporary buffer,
  // data updates were performed in place, so there is nothing to do.
  // Otherwise, copy samples from the temp buffer back to the ring buffer.
  if (source == temp_read_buffer_) {
    int pos = Tell(reader) % size_;
    if (pos + num_frames <= size_) {
      memcpy(samples_ + (pos * num_channels_), source,
             num_channels_ * num_frames * sizeof(source[0]));
    } else {
      int wrapped = size_ - pos;
      memcpy(samples_ + (pos * num_channels_), source,
             num_channels_ * wrapped * sizeof(source[0]));
      int remaining = num_frames - wrapped;
      memcpy(samples_, source + (wrapped * num_channels_),
             num_channels_ * remaining * sizeof(source[0]));
    }
  }
}

}  // namespace video_editing
