/*
 *  Copyright (c) 2018 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.
 */

#include "modules/audio_device/android/aaudio_recorder.h"

#include "api/array_view.h"
#include "modules/audio_device/android/audio_manager.h"
#include "modules/audio_device/fine_audio_buffer.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "rtc_base/timeutils.h"
#include "system_wrappers/include/sleep.h"

namespace webrtc {

enum AudioDeviceMessageType : uint32_t {
  kMessageInputStreamDisconnected,
};

AAudioRecorder::AAudioRecorder(AudioManager* audio_manager)
    : main_thread_(rtc::Thread::Current()),
      aaudio_(audio_manager, AAUDIO_DIRECTION_INPUT, this) {
  RTC_LOG(INFO) << "ctor";
  thread_checker_aaudio_.DetachFromThread();
}

AAudioRecorder::~AAudioRecorder() {
  RTC_LOG(INFO) << "dtor";
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
  Terminate();
  RTC_LOG(INFO) << "detected owerflows: " << overflow_count_;
}

int AAudioRecorder::Init() {
  RTC_LOG(INFO) << "Init";
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
  RTC_DCHECK_EQ(aaudio_.audio_parameters().channels(), 1u);
  return 0;
}

int AAudioRecorder::Terminate() {
  RTC_LOG(INFO) << "Terminate";
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
  StopRecording();
  return 0;
}

int AAudioRecorder::InitRecording() {
  RTC_LOG(INFO) << "InitRecording";
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
  RTC_DCHECK(!initialized_);
  RTC_DCHECK(!recording_);
  if (!aaudio_.Init()) {
    return -1;
  }
  initialized_ = true;
  return 0;
}

int AAudioRecorder::StartRecording() {
  RTC_LOG(INFO) << "StartRecording";
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
  RTC_DCHECK(initialized_);
  RTC_DCHECK(!recording_);
  if (fine_audio_buffer_) {
    fine_audio_buffer_->ResetPlayout();
  }
  if (!aaudio_.Start()) {
    return -1;
  }
  overflow_count_ = aaudio_.xrun_count();
  first_data_callback_ = true;
  recording_ = true;
  return 0;
}

int AAudioRecorder::StopRecording() {
  RTC_LOG(INFO) << "StopRecording";
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
  if (!initialized_ || !recording_) {
    return 0;
  }
  if (!aaudio_.Stop()) {
    return -1;
  }
  thread_checker_aaudio_.DetachFromThread();
  initialized_ = false;
  recording_ = false;
  return 0;
}

void AAudioRecorder::AttachAudioBuffer(AudioDeviceBuffer* audioBuffer) {
  RTC_LOG(INFO) << "AttachAudioBuffer";
  RTC_DCHECK(thread_checker_.CalledOnValidThread());
  audio_device_buffer_ = audioBuffer;
  const AudioParameters audio_parameters = aaudio_.audio_parameters();
  audio_device_buffer_->SetRecordingSampleRate(audio_parameters.sample_rate());
  audio_device_buffer_->SetRecordingChannels(audio_parameters.channels());
  RTC_CHECK(audio_device_buffer_);
  // Create a modified audio buffer class which allows us to deliver any number
  // of samples (and not only multiples of 10ms which WebRTC uses) to match the
  // native AAudio buffer size.
  const size_t capacity = 5 * audio_parameters.GetBytesPer10msBuffer();
  fine_audio_buffer_.reset(new FineAudioBuffer(
      audio_device_buffer_, audio_parameters.sample_rate(), capacity));
}

int AAudioRecorder::EnableBuiltInAEC(bool enable) {
  RTC_LOG(INFO) << "EnableBuiltInAEC: " << enable;
  RTC_LOG(LS_ERROR) << "Not implemented";
  return -1;
}

int AAudioRecorder::EnableBuiltInAGC(bool enable) {
  RTC_LOG(INFO) << "EnableBuiltInAGC: " << enable;
  RTC_LOG(LS_ERROR) << "Not implemented";
  return -1;
}

int AAudioRecorder::EnableBuiltInNS(bool enable) {
  RTC_LOG(INFO) << "EnableBuiltInNS: " << enable;
  RTC_LOG(LS_ERROR) << "Not implemented";
  return -1;
}

void AAudioRecorder::OnErrorCallback(aaudio_result_t error) {
  RTC_LOG(LS_ERROR) << "OnErrorCallback: " << AAudio_convertResultToText(error);
  // RTC_DCHECK(thread_checker_aaudio_.CalledOnValidThread());
  if (aaudio_.stream_state() == AAUDIO_STREAM_STATE_DISCONNECTED) {
    // The stream is disconnected and any attempt to use it will return
    // AAUDIO_ERROR_DISCONNECTED..
    RTC_LOG(WARNING) << "Input stream disconnected => restart is required";
    // AAudio documentation states: "You should not close or reopen the stream
    // from the callback, use another thread instead". A message is therefore
    // sent to the main thread to do the restart operation.
    RTC_DCHECK(main_thread_);
    main_thread_->Post(RTC_FROM_HERE, this, kMessageInputStreamDisconnected);
  }
}

// Read and process |num_frames| of data from the |audio_data| buffer.
// TODO(henrika): possibly add trace here to be included in systrace.
// See https://developer.android.com/studio/profile/systrace-commandline.html.
aaudio_data_callback_result_t AAudioRecorder::OnDataCallback(
    void* audio_data,
    int32_t num_frames) {
  // TODO(henrika): figure out why we sometimes hit this one.
  // RTC_DCHECK(thread_checker_aaudio_.CalledOnValidThread());
  // RTC_LOG(INFO) << "OnDataCallback: " << num_frames;
  // Drain the input buffer at first callback to ensure that it does not
  // contain any old data. Will also ensure that the lowest possible latency
  // is obtained.
  if (first_data_callback_) {
    RTC_LOG(INFO) << "--- First input data callback: "
                  << "device id=" << aaudio_.device_id();
    aaudio_.ClearInputStream(audio_data, num_frames);
    first_data_callback_ = false;
  }
  // Check if the overflow counter has increased and if so log a warning.
  // TODO(henrika): possible add UMA stat or capacity extension.
  const int32_t overflow_count = aaudio_.xrun_count();
  if (overflow_count > overflow_count_) {
    RTC_LOG(LS_ERROR) << "Overflow detected: " << overflow_count;
    overflow_count_ = overflow_count;
  }
  // Estimated time between an audio frame was recorded by the input device and
  // it can read on the input stream.
  latency_millis_ = aaudio_.EstimateLatencyMillis();
  // TODO(henrika): use for development only.
  if (aaudio_.frames_read() % (1000 * aaudio_.frames_per_burst()) == 0) {
    RTC_DLOG(INFO) << "input latency: " << latency_millis_
                   << ", num_frames: " << num_frames;
  }
  // Copy recorded audio in |audio_data| to the WebRTC sink using the
  // FineAudioBuffer object.
  const size_t num_bytes =
      sizeof(int16_t) * aaudio_.samples_per_frame() * num_frames;
  fine_audio_buffer_->DeliverRecordedData(
      rtc::ArrayView<const int8_t>(static_cast<const int8_t*>(audio_data),
                                   num_bytes),
      static_cast<int>(latency_millis_ + 0.5));

  return AAUDIO_CALLBACK_RESULT_CONTINUE;
}

void AAudioRecorder::OnMessage(rtc::Message* msg) {
  RTC_DCHECK_RUN_ON(&thread_checker_);
  switch (msg->message_id) {
    case kMessageInputStreamDisconnected:
      HandleStreamDisconnected();
      break;
    default:
      RTC_LOG(LS_ERROR) << "Invalid message id: " << msg->message_id;
      break;
  }
}

void AAudioRecorder::HandleStreamDisconnected() {
  RTC_DCHECK_RUN_ON(&thread_checker_);
  RTC_LOG(INFO) << "HandleStreamDisconnected";
  if (!initialized_ || !recording_) {
    return;
  }
  // Perform a restart by first closing the disconnected stream and then start
  // a new stream; this time using the new (preferred) audio input device.
  // TODO(henrika): resolve issue where a one restart attempt leads to a long
  // sequence of new calls to OnErrorCallback().
  // See b/73148976 for details.
  audio_device_buffer_->NativeAudioRecordingInterrupted();
  StopRecording();
  InitRecording();
  StartRecording();
}
}  // namespace webrtc
