/*
 *  Copyright (c) 2023 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/test_audio_device_impl.h"

#include <cstddef>
#include <cstdint>
#include <memory>
#include <optional>
#include <utility>

#include "api/array_view.h"
#include "api/environment/environment.h"
#include "api/task_queue/task_queue_factory.h"
#include "api/units/time_delta.h"
#include "modules/audio_device/audio_device_buffer.h"
#include "modules/audio_device/audio_device_generic.h"
#include "modules/audio_device/include/test_audio_device.h"
#include "rtc_base/checks.h"
#include "rtc_base/synchronization/mutex.h"
#include "rtc_base/task_utils/repeating_task.h"

namespace webrtc {
namespace {

constexpr int kFrameLengthUs = 10000;

}  // namespace

TestAudioDevice::TestAudioDevice(
    const Environment& env,
    std::unique_ptr<TestAudioDeviceModule::Capturer> capturer,
    std::unique_ptr<TestAudioDeviceModule::Renderer> renderer,
    float speed)
    : env_(env),
      capturer_(std::move(capturer)),
      renderer_(std::move(renderer)),
      process_interval_us_(kFrameLengthUs / speed),
      audio_buffer_(nullptr),
      rendering_(false),
      capturing_(false) {
  auto good_sample_rate = [](int sr) {
    return sr == 8000 || sr == 16000 || sr == 24000 || sr == 32000 ||
           sr == 44100 || sr == 48000;
  };

  if (renderer_) {
    const int sample_rate = renderer_->SamplingFrequency();
    playout_buffer_.resize(TestAudioDeviceModule::SamplesPerFrame(sample_rate) *
                               renderer_->NumChannels(),
                           0);
    RTC_CHECK(good_sample_rate(sample_rate));
  }
  if (capturer_) {
    RTC_CHECK(good_sample_rate(capturer_->SamplingFrequency()));
  }
}

AudioDeviceGeneric::InitStatus TestAudioDevice::Init() {
  task_queue_ = env_.task_queue_factory().CreateTaskQueue(
      "TestAudioDeviceModuleImpl", TaskQueueFactory::Priority::NORMAL);

  RepeatingTaskHandle::Start(task_queue_.get(), [this]() {
    ProcessAudio();
    return TimeDelta::Micros(process_interval_us_);
  });
  return InitStatus::OK;
}

int32_t TestAudioDevice::PlayoutIsAvailable(bool& available) {
  MutexLock lock(&lock_);
  available = renderer_ != nullptr;
  return 0;
}

int32_t TestAudioDevice::InitPlayout() {
  MutexLock lock(&lock_);

  if (rendering_) {
    return -1;
  }

  if (audio_buffer_ != nullptr && renderer_ != nullptr) {
    // Update webrtc audio buffer with the selected parameters
    audio_buffer_->SetPlayoutSampleRate(renderer_->SamplingFrequency());
    audio_buffer_->SetPlayoutChannels(renderer_->NumChannels());
  }
  rendering_initialized_ = true;
  return 0;
}

bool TestAudioDevice::PlayoutIsInitialized() const {
  MutexLock lock(&lock_);
  return rendering_initialized_;
}

int32_t TestAudioDevice::StartPlayout() {
  MutexLock lock(&lock_);
  RTC_CHECK(renderer_);
  rendering_ = true;
  return 0;
}

int32_t TestAudioDevice::StopPlayout() {
  MutexLock lock(&lock_);
  rendering_ = false;
  return 0;
}

int32_t TestAudioDevice::RecordingIsAvailable(bool& available) {
  MutexLock lock(&lock_);
  available = capturer_ != nullptr;
  return 0;
}

int32_t TestAudioDevice::InitRecording() {
  MutexLock lock(&lock_);

  if (capturing_) {
    return -1;
  }

  if (audio_buffer_ != nullptr && capturer_ != nullptr) {
    // Update webrtc audio buffer with the selected parameters
    audio_buffer_->SetRecordingSampleRate(capturer_->SamplingFrequency());
    audio_buffer_->SetRecordingChannels(capturer_->NumChannels());
  }
  capturing_initialized_ = true;
  return 0;
}

bool TestAudioDevice::RecordingIsInitialized() const {
  MutexLock lock(&lock_);
  return capturing_initialized_;
}

int32_t TestAudioDevice::StartRecording() {
  MutexLock lock(&lock_);
  capturing_ = true;
  return 0;
}

int32_t TestAudioDevice::StopRecording() {
  MutexLock lock(&lock_);
  capturing_ = false;
  return 0;
}

bool TestAudioDevice::Playing() const {
  MutexLock lock(&lock_);
  return rendering_;
}

bool TestAudioDevice::Recording() const {
  MutexLock lock(&lock_);
  return capturing_;
}

void TestAudioDevice::ProcessAudio() {
  MutexLock lock(&lock_);
  if (audio_buffer_ == nullptr) {
    return;
  }
  if (capturing_ && capturer_ != nullptr) {
    // Capture 10ms of audio. 2 bytes per sample.
    const bool keep_capturing = capturer_->Capture(&recording_buffer_);
    if (!recording_buffer_.empty()) {
      audio_buffer_->SetRecordedBuffer(
          recording_buffer_.data(),
          recording_buffer_.size() / capturer_->NumChannels(),
          std::make_optional(env_.clock().CurrentTime().ns()));
      audio_buffer_->DeliverRecordedData();
    }
    if (!keep_capturing) {
      capturing_ = false;
    }
  }
  if (rendering_) {
    const int sampling_frequency = renderer_->SamplingFrequency();
    int32_t samples_per_channel = audio_buffer_->RequestPlayoutData(
        TestAudioDeviceModule::SamplesPerFrame(sampling_frequency));
    audio_buffer_->GetPlayoutData(playout_buffer_.data());
    size_t samples_out = samples_per_channel * renderer_->NumChannels();
    RTC_CHECK_LE(samples_out, playout_buffer_.size());
    const bool keep_rendering = renderer_->Render(
        ArrayView<const int16_t>(playout_buffer_.data(), samples_out));
    if (!keep_rendering) {
      rendering_ = false;
    }
  }
}

void TestAudioDevice::AttachAudioBuffer(AudioDeviceBuffer* audio_buffer) {
  MutexLock lock(&lock_);
  RTC_DCHECK(audio_buffer || audio_buffer_);
  audio_buffer_ = audio_buffer;

  if (renderer_ != nullptr) {
    audio_buffer_->SetPlayoutSampleRate(renderer_->SamplingFrequency());
    audio_buffer_->SetPlayoutChannels(renderer_->NumChannels());
  }
  if (capturer_ != nullptr) {
    audio_buffer_->SetRecordingSampleRate(capturer_->SamplingFrequency());
    audio_buffer_->SetRecordingChannels(capturer_->NumChannels());
  }
}

}  // namespace webrtc
