// Copyright (c) 2016 Samsung Electronics Co., Ltd 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/audio_sink.h"
#include "starboard/log.h"
#include "starboard/mutex.h"
#include "starboard/tizen/shared/audio/audio_sink_private.h"

#define CHECK_CAPI_AUDIO_ERROR(func)                            \
  if (capi_ret != AUDIO_IO_ERROR_NONE) {                        \
    SB_DLOG(ERROR) << "[MEDIA] " #func " (" << capi_ret << ", " \
                   << GetCAPIErrorString(capi_ret) << ")";      \
    return;                                                     \
  }

const int kSampleByte = 2;

SbAudioSinkPrivate::SbAudioSinkPrivate(
    int channels,
    int sampling_frequency_hz,
    SbMediaAudioSampleType audio_sample_type,
    SbMediaAudioFrameStorageType audio_frame_storage_type,
    SbAudioSinkFrameBuffers frame_buffers,
    int frames_per_channel,
    SbAudioSinkUpdateSourceStatusFunc update_source_status_func,
    SbAudioSinkConsumeFramesFunc consume_frames_func,
    void* context)
    : channels_(channels),
      sampling_frequency_hz_(sampling_frequency_hz),
      audio_sample_type_(audio_sample_type),
      audio_frame_storage_type_(audio_frame_storage_type),
      frame_buffers_(frame_buffers),
      frames_per_channel_(frames_per_channel),
      update_source_status_func_(update_source_status_func),
      consume_frames_func_(consume_frames_func),
      context_(context),
      destroying_(false),
      is_paused_(true) {
  SB_DLOG(INFO) << "[MEDIA] SbAudioSinkPrivate : "
                << "channels " << channels << ", frequency "
                << sampling_frequency_hz << ", sample_type "
                << audio_sample_type << ", storage_type "
                << audio_frame_storage_type << ", frame_buffers "
                << static_cast<int>(frame_buffers) << ", frame_buff_sz "
                << frames_per_channel;

  int capi_ret;
  capi_ret = audio_out_create_new(sampling_frequency_hz, AUDIO_CHANNEL_STEREO,
                                  AUDIO_SAMPLE_TYPE_S16_LE,  // kSampleByte = 2
                                  &capi_audio_out_);
  CHECK_CAPI_AUDIO_ERROR(audio_out_create_new);

  capi_ret = audio_out_set_interrupted_cb(capi_audio_out_,
                                          OnCAPIAudioIOInterrupted_CB, this);
  CHECK_CAPI_AUDIO_ERROR(audio_out_set_interrupted_cb);

  // Starts the thread
  audio_out_thread_ =
      SbThreadCreate(0, kSbThreadPriorityRealTime, kSbThreadNoAffinity, true,
                     "tizen_audio_out", AudioSinkThreadProc_CB, this);
  SB_DCHECK(SbThreadIsValid(audio_out_thread_));
}

SbAudioSinkPrivate::~SbAudioSinkPrivate() {
  // Stop the thread
  {
    starboard::ScopedLock lock(mutex_);
    destroying_ = true;
  }
  if (SbThreadIsValid(audio_out_thread_)) {
    SB_DLOG(INFO) << "[MEDIA] wait for audio sink thread exit";
    SbThreadJoin(audio_out_thread_, NULL);
  } else {
    SB_DLOG(INFO) << "[MEDIA] audio sink thread is invalid. skip waiting";
  }

  // destroy capi audio
  if (capi_audio_out_) {
    int ret = audio_out_destroy(capi_audio_out_);
    if (ret != AUDIO_IO_ERROR_NONE) {
      SB_DLOG(ERROR) << "audio_out_destroy failed (" << ret << ")";
    }
  }
}

bool SbAudioSinkPrivate::IsValid() {
  return SbThreadIsValid(audio_out_thread_);
}

// static callbacks
void SbAudioSinkPrivate::OnCAPIAudioIOInterrupted_CB(
    audio_io_interrupted_code_e code,
    void* user_data) {
  SbAudioSinkPrivate* audio_sink =
      reinterpret_cast<SbAudioSinkPrivate*>(user_data);
  if (audio_sink) {
    audio_sink->OnCAPIAudioIOInterrupted(code);
  }
}
void SbAudioSinkPrivate::OnCAPIAudioStreamWrite_CB(
    audio_out_h handle,
    size_t nbytes,
    void* user_data) {  // not used
  SbAudioSinkPrivate* audio_sink =
      reinterpret_cast<SbAudioSinkPrivate*>(user_data);
  if (audio_sink) {
    audio_sink->OnCAPIAudioStreamWrite(handle, nbytes);
  }
}
void* SbAudioSinkPrivate::AudioSinkThreadProc_CB(void* context) {
  SbAudioSinkPrivate* audio_sink =
      reinterpret_cast<SbAudioSinkPrivate*>(context);
  if (audio_sink) {
    return audio_sink->AudioSinkThreadProc();
  }
  return NULL;
}

const char* SbAudioSinkPrivate::GetCAPIErrorString(int ret) {
  // TODO : Get CAPI error and print log
  return "Unknown";
}

void SbAudioSinkPrivate::OnCAPIAudioIOInterrupted(
    audio_io_interrupted_code_e code) {
  SB_DLOG(WARNING) << "Play interrupted: audio_io_interrupted_code_e : "
                   << code;
}

void SbAudioSinkPrivate::OnCAPIAudioStreamWrite(audio_out_h handle,
                                                size_t nbytes) {
  SB_DLOG(INFO) << "[MEDIA] OnAudioStreamWrite (not used) - request " << nbytes;
}

void* SbAudioSinkPrivate::AudioSinkThreadProc() {
  void* buf;
  int bytes_to_fill;
  int bytes_written;
  int bytes_per_frame = kSampleByte;
  int consumed_frames;

  SB_DLOG(INFO) << "[MEDIA] sink thread started";

  for (;;) {
    {
      starboard::ScopedLock lock(mutex_);
      if (destroying_) {
        break;
      }
    }

    int frames_in_buffer, offset_in_frames;
    bool is_playing, is_eos_reached;
    update_source_status_func_(&frames_in_buffer, &offset_in_frames,
                               &is_playing, &is_eos_reached, context_);

    if (is_playing) {
      buf = reinterpret_cast<uint8_t*>(frame_buffers_[0]) +
            offset_in_frames * bytes_per_frame;
      if (offset_in_frames + frames_in_buffer <= frames_per_channel_) {
        bytes_to_fill = frames_in_buffer * bytes_per_frame;
      } else {
        bytes_to_fill =
            (frames_per_channel_ - offset_in_frames) * bytes_per_frame;
      }

      if (is_paused_) {
        // audio_out_resume(capi_audio_out_);
        audio_out_prepare(capi_audio_out_);
        is_paused_ = false;
        SB_DLOG(INFO) << "[MEDIA] audio_out_resume";
      }

      bytes_written = audio_out_write(capi_audio_out_, buf, bytes_to_fill);

      if (bytes_written < 0) {
        SB_DLOG(ERROR) << "[MEDIA] audio_out_write error (" << bytes_written
                       << ", " << GetCAPIErrorString(bytes_written) << ")";
        break;
      }
      consumed_frames = bytes_written / bytes_per_frame;

      // SbThreadSleep(consumed_frames * kSbTimeSecond /
      // sampling_frequency_hz_);
      consume_frames_func_(consumed_frames, context_);
    } else {
      if (!is_paused_) {
        audio_out_unprepare(capi_audio_out_);
        is_paused_ = true;
        SB_DLOG(INFO) << "[MEDIA] audio_out_pause";
      }
      // Wait for five millisecond if we are paused.
      SbThreadSleep(kSbTimeMillisecond * 5);
    }
  }

  SB_DLOG(INFO) << "[MEDIA] sink thread exited";
  return NULL;
}
