// 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_sink.h"

#include <basetyps.h>
#include <wrl.h>
#include <xaudio2.h>

#include <limits>
#include <sstream>
#include <string>

#include "starboard/configuration.h"
#include "starboard/log.h"
#include "starboard/mutex.h"
#include "starboard/thread.h"
#include "starboard/time.h"

using Microsoft::WRL::ComPtr;

namespace {
// Fails an SB_DCHECK if an HRESULT is not S_OK
void CHECK_HRESULT_OK(HRESULT hr) {
  SB_DCHECK(SUCCEEDED(hr)) << std::hex << hr;
}

const int kMaxBuffersSubmittedPerLoop = 2;

std::string GenerateThreadName() {
  static int s_count = 0;
  std::stringstream ss;
  ss << "AudioOut_" << s_count++;
  return ss.str();
}
}  // namespace.

namespace starboard {
namespace shared {
namespace win32 {

class XAudioAudioSink : public SbAudioSinkPrivate {
 public:
  XAudioAudioSink(Type* type,
                  const WAVEFORMATEX& wfx,
                  SbAudioSinkFrameBuffers frame_buffers,
                  int frame_buffers_size_in_frames,
                  SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
                  SbAudioSinkConsumeFramesFunc consume_frame_func,
                  void* context);
  ~XAudioAudioSink() SB_OVERRIDE;

  bool IsType(Type* type) SB_OVERRIDE { return type_ == type; }
  void SetPlaybackRate(double playback_rate) SB_OVERRIDE {
    SB_DCHECK(playback_rate >= 0.0);
    if (playback_rate != 0.0 && playback_rate != 1.0) {
      SB_NOTIMPLEMENTED() << "TODO: Only playback rates of 0.0 and 1.0 are "
                             "currently supported.";
      playback_rate = (playback_rate > 0.0) ? 1.0 : 0.0;
    }
    ScopedLock lock(mutex_);
    playback_rate_ = playback_rate;
  }

 private:
  static void* ThreadEntryPoint(void* context);
  void AudioThreadFunc();
  void SubmitSourceBuffer(int offset_in_frames, int count_frames);

  XAudioAudioSinkType* type_;
  SbAudioSinkUpdateSourceStatusFunc update_source_status_func_;
  SbAudioSinkConsumeFramesFunc consume_frame_func_;
  void* context_;

  SbThread audio_out_thread_;

  SbAudioSinkFrameBuffers frame_buffers_;
  int frame_buffers_size_in_frames_;
  WAVEFORMATEX wfx_;

  // Note: despite some documentation to the contrary, it appears
  // that IXAudio2SourceVoice cannot be a ComPtr.
  IXAudio2SourceVoice* source_voice_;

  // mutex_ protects only destroying_ and playback_rate_.
  // Everything else is immutable
  // after the constructor.
  ::starboard::Mutex mutex_;
  bool destroying_;
  double playback_rate_;
};

XAudioAudioSink::XAudioAudioSink(
    Type* type,
    const WAVEFORMATEX& wfx,
    SbAudioSinkFrameBuffers frame_buffers,
    int frame_buffers_size_in_frames,
    SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
    SbAudioSinkConsumeFramesFunc consume_frame_func,
    void* context)
    : type_(static_cast<XAudioAudioSinkType*>(type)),
      update_source_status_func_(update_source_status_func),
      consume_frame_func_(consume_frame_func),
      context_(context),
      audio_out_thread_(kSbThreadInvalid),
      frame_buffers_(frame_buffers),
      frame_buffers_size_in_frames_(frame_buffers_size_in_frames),
      wfx_(wfx),
      destroying_(false),
      playback_rate_(1.0) {
  // TODO: Check MaxFrequencyRatio
  CHECK_HRESULT_OK(
      type_->x_audio2_->CreateSourceVoice(&source_voice_, &wfx, 0,
                                          /*MaxFrequencyRatio = */ 1.0));

  CHECK_HRESULT_OK(source_voice_->Stop(0));

  std::string thread_name = GenerateThreadName();

  audio_out_thread_ = SbThreadCreate(
      0, kSbThreadPriorityRealTime, kSbThreadNoAffinity, true,
      thread_name.c_str(), &XAudioAudioSink::ThreadEntryPoint, this);
  SB_DCHECK(SbThreadIsValid(audio_out_thread_));
}

XAudioAudioSink::~XAudioAudioSink() {
  {
    ScopedLock lock(mutex_);
    destroying_ = true;
  }
  SbThreadJoin(audio_out_thread_, nullptr);
  source_voice_->DestroyVoice();
}

// static
void* XAudioAudioSink::ThreadEntryPoint(void* context) {
  SB_DCHECK(context);
  XAudioAudioSink* sink = static_cast<XAudioAudioSink*>(context);
  sink->AudioThreadFunc();

  return nullptr;
}

void XAudioAudioSink::SubmitSourceBuffer(int offset_in_frames,
                                         int count_frames) {
  XAUDIO2_BUFFER audio_buffer_info;

  audio_buffer_info.Flags = 0;
  audio_buffer_info.AudioBytes = wfx_.nChannels *
                                 frame_buffers_size_in_frames_ *
                                 (wfx_.wBitsPerSample / 8);
  audio_buffer_info.pAudioData = static_cast<const BYTE*>(frame_buffers_[0]);
  audio_buffer_info.PlayBegin = offset_in_frames;
  audio_buffer_info.PlayLength = count_frames;
  audio_buffer_info.LoopBegin = 0;
  audio_buffer_info.LoopLength = 0;
  audio_buffer_info.LoopCount = 0;
  audio_buffer_info.pContext = nullptr;
  CHECK_HRESULT_OK(source_voice_->SubmitSourceBuffer(&audio_buffer_info));
}

void XAudioAudioSink::AudioThreadFunc() {
  const int kMaxFramesToConsumePerRequest = 1024;

  int submitted_frames = 0;
  uint64_t samples_played = 0;
  int queued_buffers = 0;
  bool was_playing = false;  // The player starts out playing by default.
  for (;;) {
    {
      ScopedLock lock(mutex_);
      if (destroying_) {
        break;
      }
    }
    int frames_in_buffer, offset_in_frames;
    bool is_playing, is_eos_reached;
    bool is_playback_rate_zero;
    {
      ScopedLock lock(mutex_);
      is_playback_rate_zero = playback_rate_ == 0.0;
    }
    update_source_status_func_(&frames_in_buffer, &offset_in_frames,
                               &is_playing, &is_eos_reached, context_);
    if (is_playback_rate_zero) {
      is_playing = false;
    }

    if (is_playing != was_playing) {
      if (is_playing) {
        CHECK_HRESULT_OK(source_voice_->Start(0));
      } else {
        CHECK_HRESULT_OK(source_voice_->Stop(0));
      }
    }
    was_playing = is_playing;

    // TODO: make sure that frames_in_buffer is large enough
    // that it exceeds the voice state pool interval
    if (!is_playing || frames_in_buffer == 0 || is_playback_rate_zero) {
      SbThreadSleep(kSbTimeMillisecond * 5);
      continue;
    }
    int unsubmitted_frames = frames_in_buffer - submitted_frames;
    int unsubmitted_start =
        (offset_in_frames + submitted_frames) % frame_buffers_size_in_frames_;
    if (unsubmitted_frames == 0 ||
        queued_buffers +
            kMaxBuffersSubmittedPerLoop > XAUDIO2_MAX_QUEUED_BUFFERS) {
      // submit nothing
    } else if (unsubmitted_start + unsubmitted_frames <=
               frame_buffers_size_in_frames_) {
      SubmitSourceBuffer(unsubmitted_start, unsubmitted_frames);
    } else {
      int count_tail_frames = frame_buffers_size_in_frames_ - unsubmitted_start;
      // Note since we can submit up to two source buffers at a time,
      // kMaxBuffersSubmittedPerLoop = 2.
      SubmitSourceBuffer(unsubmitted_start, count_tail_frames);
      SubmitSourceBuffer(0, unsubmitted_frames - count_tail_frames);
    }
    submitted_frames = frames_in_buffer;

    SbThreadSleep(kSbTimeMillisecond);

    XAUDIO2_VOICE_STATE voice_state;
    source_voice_->GetState(&voice_state);

    int64_t consumed_frames = voice_state.SamplesPlayed - samples_played;
    SB_DCHECK(consumed_frames >= 0);
    SB_DCHECK(consumed_frames < std::numeric_limits<int>::max());
    int consumed_frames_int = static_cast<int>(consumed_frames);

    consume_frame_func_(consumed_frames_int, context_);
    submitted_frames -= consumed_frames_int;
    samples_played = voice_state.SamplesPlayed;
    queued_buffers = voice_state.BuffersQueued;
  }
}

namespace {

WORD SampleTypeToFormatTag(SbMediaAudioSampleType type) {
  switch (type) {
    case kSbMediaAudioSampleTypeInt16:
      return WAVE_FORMAT_PCM;
    case kSbMediaAudioSampleTypeFloat32:
      return WAVE_FORMAT_IEEE_FLOAT;
    default:
      SB_NOTREACHED();
      return 0;
  }
}

WORD SampleTypeToBitsPerSample(SbMediaAudioSampleType type) {
  switch (type) {
    case kSbMediaAudioSampleTypeInt16:
      return 16;
    case kSbMediaAudioSampleTypeFloat32:
      return 32;
    default:
      SB_NOTREACHED();
      return 0;
  }
}

}  // namespace

XAudioAudioSinkType::XAudioAudioSinkType() {
  CHECK_HRESULT_OK(XAudio2Create(&x_audio2_, 0, XAUDIO2_DEFAULT_PROCESSOR));
  CHECK_HRESULT_OK(x_audio2_->CreateMasteringVoice(&mastering_voice_));
}

SbAudioSink XAudioAudioSinkType::Create(
    int channels,
    int sampling_frequency_hz,
    SbMediaAudioSampleType audio_sample_type,
    SbMediaAudioFrameStorageType audio_frame_storage_type,
    SbAudioSinkFrameBuffers frame_buffers,
    int frame_buffers_size_in_frames,
    SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
    SbAudioSinkConsumeFramesFunc consume_frames_func,
    void* context) {
  SB_DCHECK(audio_frame_storage_type ==
            kSbMediaAudioFrameStorageTypeInterleaved);

  WAVEFORMATEX wfx;

  wfx.wFormatTag = SampleTypeToFormatTag(audio_sample_type);
  wfx.nChannels = static_cast<WORD>(channels);
  wfx.nSamplesPerSec = sampling_frequency_hz;
  wfx.nAvgBytesPerSec = channels *
                        SampleTypeToBitsPerSample(audio_sample_type) *
                        sampling_frequency_hz / 8;
  wfx.wBitsPerSample = SampleTypeToBitsPerSample(audio_sample_type);
  wfx.nBlockAlign = static_cast<WORD>((channels * wfx.wBitsPerSample) / 8);
  wfx.cbSize = 0;

  return new XAudioAudioSink(
      this, wfx, frame_buffers, frame_buffers_size_in_frames,
      update_source_status_func, consume_frames_func, context);
}

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

namespace {
SbAudioSinkPrivate::Type* audio_sink_;
}  // namespace

// static
void SbAudioSinkPrivate::PlatformInitialize() {
  SB_DCHECK(!audio_sink_);
  audio_sink_ = new starboard::shared::win32::XAudioAudioSinkType();
  SetPrimaryType(audio_sink_);
  EnableFallbackToStub();
}

// static
void SbAudioSinkPrivate::PlatformTearDown() {
  SB_DCHECK(audio_sink_ == GetPrimaryType());
  SetPrimaryType(nullptr);
  delete audio_sink_;
  audio_sink_ = nullptr;
}
