// Copyright 2017 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 "starboard/shared/win32/audio_decoder_thread.h"

#include <deque>
#include <vector>

namespace starboard {
namespace shared {
namespace win32 {
namespace {

// Size of the queue for audio units.
const size_t kMaxProcessingElements = 64;

size_t WriteAsMuchAsPossible(
    std::deque<scoped_refptr<InputBuffer> >* data_queue,
    AbstractWin32AudioDecoder* audio_decoder) {
  const size_t original_size = data_queue->size();
  while (!data_queue->empty()) {
    scoped_refptr<InputBuffer> buff = data_queue->front();
    data_queue->pop_front();

    if (buff) {
      const bool write_ok = audio_decoder->TryWrite(*buff);

      if (!write_ok) {
        data_queue->push_front(buff);
        break;
      }
    } else {
      audio_decoder->WriteEndOfStream();
    }
  }
  return original_size - data_queue->size();
}

std::vector<DecodedAudioPtr> ReadAllDecodedAudioSamples(
    AbstractWin32AudioDecoder* audio_decoder) {
  std::vector<DecodedAudioPtr> decoded_audio_out;
  while (DecodedAudioPtr decoded_datum = audio_decoder->ProcessAndRead()) {
    decoded_audio_out.push_back(decoded_datum);
  }
  return decoded_audio_out;
}

}  // namespace.

AudioDecoderThread::AudioDecoderThread(AbstractWin32AudioDecoder* decoder_impl,
                                       AudioDecodedCallback* callback)
    : SimpleThread("AudioDecoderThread"),
      win32_audio_decoder_(decoder_impl),
      callback_(callback) {
  Start();
}

AudioDecoderThread::~AudioDecoderThread() {
  Join();
}

bool AudioDecoderThread::QueueInput(const scoped_refptr<InputBuffer>& buffer) {
  {
    ::starboard::ScopedLock lock(input_buffer_queue_mutex_);
    input_buffer_queue_.push_back(buffer);
  }

  // increment() returns the previous value.
  size_t element_count = processing_elements_.increment() + 1;
  semaphore_.Put();
  return element_count < kMaxProcessingElements;
}

void AudioDecoderThread::QueueEndOfStream() {
  scoped_refptr<InputBuffer> empty;
  QueueInput(empty);
}

void AudioDecoderThread::Run() {
  std::deque<scoped_refptr<InputBuffer> > local_queue;

  while (!join_called()) {
    TransferPendingInputTo(&local_queue);
    bool work_done = !local_queue.empty();
    size_t number_written =
        WriteAsMuchAsPossible(&local_queue, win32_audio_decoder_);
    processing_elements_.fetch_sub(static_cast<int32_t>(number_written));

    std::vector<DecodedAudioPtr> decoded_audio =
        ReadAllDecodedAudioSamples(win32_audio_decoder_);

    if (!decoded_audio.empty()) {
      work_done = true;
      for (auto it = decoded_audio.begin(); it != decoded_audio.end(); ++it) {
        callback_->OnAudioDecoded(*it);
      }
    }

    if (!work_done) {
      semaphore_.TakeWait(kSbTimeMillisecond);
    }
  }
}

void AudioDecoderThread::TransferPendingInputTo(
    std::deque<scoped_refptr<InputBuffer> >* destination) {
  ::starboard::ScopedLock lock(input_buffer_queue_mutex_);
  while (!input_buffer_queue_.empty()) {
    destination->push_back(input_buffer_queue_.front());
    input_buffer_queue_.pop_front();
  }
}

}  // namespace win32
}  // namespace shared
}  // namespace starboard
