/*
 *  Copyright (c) 2017 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 <utility>

#include "webrtc/modules/audio_processing/aec_dump/aec_dump_impl.h"

#include "webrtc/modules/audio_processing/aec_dump/aec_dump_factory.h"
#include "webrtc/rtc_base/checks.h"
#include "webrtc/rtc_base/event.h"
#include "webrtc/rtc_base/ptr_util.h"

namespace webrtc {

namespace {
void CopyFromConfigToEvent(const webrtc::InternalAPMConfig& config,
                           webrtc::audioproc::Config* pb_cfg) {
  pb_cfg->set_aec_enabled(config.aec_enabled);
  pb_cfg->set_aec_delay_agnostic_enabled(config.aec_delay_agnostic_enabled);
  pb_cfg->set_aec_drift_compensation_enabled(
      config.aec_drift_compensation_enabled);
  pb_cfg->set_aec_extended_filter_enabled(config.aec_extended_filter_enabled);
  pb_cfg->set_aec_suppression_level(config.aec_suppression_level);

  pb_cfg->set_aecm_enabled(config.aecm_enabled);
  pb_cfg->set_aecm_comfort_noise_enabled(config.aecm_comfort_noise_enabled);
  pb_cfg->set_aecm_routing_mode(config.aecm_routing_mode);

  pb_cfg->set_agc_enabled(config.agc_enabled);
  pb_cfg->set_agc_mode(config.agc_mode);
  pb_cfg->set_agc_limiter_enabled(config.agc_limiter_enabled);
  pb_cfg->set_noise_robust_agc_enabled(config.noise_robust_agc_enabled);

  pb_cfg->set_hpf_enabled(config.hpf_enabled);

  pb_cfg->set_ns_enabled(config.ns_enabled);
  pb_cfg->set_ns_level(config.ns_level);

  pb_cfg->set_transient_suppression_enabled(
      config.transient_suppression_enabled);
  pb_cfg->set_intelligibility_enhancer_enabled(
      config.intelligibility_enhancer_enabled);

  pb_cfg->set_experiments_description(config.experiments_description);
}

}  // namespace

AecDumpImpl::AecDumpImpl(std::unique_ptr<FileWrapper> debug_file,
                         int64_t max_log_size_bytes,
                         rtc::TaskQueue* worker_queue)
    : debug_file_(std::move(debug_file)),
      num_bytes_left_for_log_(max_log_size_bytes),
      worker_queue_(worker_queue),
      capture_stream_info_(CreateWriteToFileTask()) {}

AecDumpImpl::~AecDumpImpl() {
  // Block until all tasks have finished running.
  rtc::Event thread_sync_event(false /* manual_reset */, false);
  worker_queue_->PostTask([&thread_sync_event] { thread_sync_event.Set(); });
  // Wait until the event has been signaled with .Set(). By then all
  // pending tasks will have finished.
  thread_sync_event.Wait(rtc::Event::kForever);
}

void AecDumpImpl::WriteInitMessage(
    const InternalAPMStreamsConfig& streams_config) {
  auto task = CreateWriteToFileTask();
  auto* event = task->GetEvent();
  event->set_type(audioproc::Event::INIT);
  audioproc::Init* msg = event->mutable_init();

  msg->set_sample_rate(streams_config.input_sample_rate);
  msg->set_output_sample_rate(streams_config.output_sample_rate);
  msg->set_reverse_sample_rate(streams_config.render_input_sample_rate);
  msg->set_reverse_output_sample_rate(streams_config.render_output_sample_rate);

  msg->set_num_input_channels(
      static_cast<int32_t>(streams_config.input_num_channels));
  msg->set_num_output_channels(
      static_cast<int32_t>(streams_config.output_num_channels));
  msg->set_num_reverse_channels(
      static_cast<int32_t>(streams_config.render_input_num_channels));
  msg->set_num_reverse_output_channels(
      streams_config.render_output_num_channels);

  worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
}

void AecDumpImpl::AddCaptureStreamInput(const FloatAudioFrame& src) {
  capture_stream_info_.AddInput(src);
}

void AecDumpImpl::AddCaptureStreamOutput(const FloatAudioFrame& src) {
  capture_stream_info_.AddOutput(src);
}

void AecDumpImpl::AddCaptureStreamInput(const AudioFrame& frame) {
  capture_stream_info_.AddInput(frame);
}

void AecDumpImpl::AddCaptureStreamOutput(const AudioFrame& frame) {
  capture_stream_info_.AddOutput(frame);
}

void AecDumpImpl::AddAudioProcessingState(const AudioProcessingState& state) {
  capture_stream_info_.AddAudioProcessingState(state);
}

void AecDumpImpl::WriteCaptureStreamMessage() {
  auto task = capture_stream_info_.GetTask();
  RTC_DCHECK(task);
  std::move(task);
  worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
  capture_stream_info_.SetTask(CreateWriteToFileTask());
}

void AecDumpImpl::WriteRenderStreamMessage(const AudioFrame& frame) {
  auto task = CreateWriteToFileTask();
  auto* event = task->GetEvent();

  event->set_type(audioproc::Event::REVERSE_STREAM);
  audioproc::ReverseStream* msg = event->mutable_reverse_stream();
  const size_t data_size =
      sizeof(int16_t) * frame.samples_per_channel_ * frame.num_channels_;
  msg->set_data(frame.data(), data_size);

  worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
}

void AecDumpImpl::WriteRenderStreamMessage(const FloatAudioFrame& src) {
  auto task = CreateWriteToFileTask();
  auto* event = task->GetEvent();

  event->set_type(audioproc::Event::REVERSE_STREAM);

  audioproc::ReverseStream* msg = event->mutable_reverse_stream();

  for (size_t i = 0; i < src.num_channels(); ++i) {
    const auto& channel_view = src.channel(i);
    msg->add_channel(channel_view.begin(), sizeof(float) * channel_view.size());
  }

  worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
}

void AecDumpImpl::WriteConfig(const InternalAPMConfig& config) {
  RTC_DCHECK_RUNS_SERIALIZED(&race_checker_);
  auto task = CreateWriteToFileTask();
  auto* event = task->GetEvent();
  event->set_type(audioproc::Event::CONFIG);
  CopyFromConfigToEvent(config, event->mutable_config());
  worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(std::move(task)));
}

std::unique_ptr<WriteToFileTask> AecDumpImpl::CreateWriteToFileTask() {
  return rtc::MakeUnique<WriteToFileTask>(debug_file_.get(),
                                          &num_bytes_left_for_log_);
}

std::unique_ptr<AecDump> AecDumpFactory::Create(rtc::PlatformFile file,
                                                int64_t max_log_size_bytes,
                                                rtc::TaskQueue* worker_queue) {
  RTC_DCHECK(worker_queue);
  std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
  FILE* handle = rtc::FdopenPlatformFileForWriting(file);
  if (!handle) {
    return nullptr;
  }
  if (!debug_file->OpenFromFileHandle(handle)) {
    return nullptr;
  }
  return rtc::MakeUnique<AecDumpImpl>(std::move(debug_file), max_log_size_bytes,
                                      worker_queue);
}

std::unique_ptr<AecDump> AecDumpFactory::Create(std::string file_name,
                                                int64_t max_log_size_bytes,
                                                rtc::TaskQueue* worker_queue) {
  RTC_DCHECK(worker_queue);
  std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
  if (!debug_file->OpenFile(file_name.c_str(), false)) {
    return nullptr;
  }
  return rtc::MakeUnique<AecDumpImpl>(std::move(debug_file), max_log_size_bytes,
                                      worker_queue);
}

std::unique_ptr<AecDump> AecDumpFactory::Create(FILE* handle,
                                                int64_t max_log_size_bytes,
                                                rtc::TaskQueue* worker_queue) {
  RTC_DCHECK(worker_queue);
  RTC_DCHECK(handle);
  std::unique_ptr<FileWrapper> debug_file(FileWrapper::Create());
  if (!debug_file->OpenFromFileHandle(handle)) {
    return nullptr;
  }
  return rtc::MakeUnique<AecDumpImpl>(std::move(debug_file), max_log_size_bytes,
                                      worker_queue);
}
}  // namespace webrtc
