/*
 *  Copyright (c) 2016 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_processing/test/wav_based_simulator.h"

#include <cstdio>
#include <iostream>
#include <memory>
#include <utility>
#include <vector>

#include "absl/base/nullability.h"
#include "absl/strings/string_view.h"
#include "api/audio/audio_processing.h"
#include "api/scoped_refptr.h"
#include "common_audio/wav_file.h"
#include "modules/audio_processing/test/audio_processing_simulator.h"
#include "modules/audio_processing/test/test_utils.h"
#include "rtc_base/checks.h"
#include "rtc_base/system/file_wrapper.h"

namespace webrtc {
namespace test {

std::vector<WavBasedSimulator::SimulationEventType>
WavBasedSimulator::GetCustomEventChain(absl::string_view filename) {
  std::vector<WavBasedSimulator::SimulationEventType> call_chain;
  FileWrapper file_wrapper = FileWrapper::OpenReadOnly(filename);

  RTC_CHECK(file_wrapper.is_open())
      << "Could not open the custom call order file, reverting "
         "to using the default call order";

  char c;
  size_t num_read = file_wrapper.Read(&c, sizeof(char));
  while (num_read > 0) {
    switch (c) {
      case 'r':
        call_chain.push_back(SimulationEventType::kProcessReverseStream);
        break;
      case 'c':
        call_chain.push_back(SimulationEventType::kProcessStream);
        break;
      case '\n':
        break;
      default:
        RTC_FATAL() << "Incorrect custom call order file";
    }

    num_read = file_wrapper.Read(&c, sizeof(char));
  }

  return call_chain;
}

WavBasedSimulator::WavBasedSimulator(
    const SimulationSettings& settings,
    absl_nonnull scoped_refptr<AudioProcessing> audio_processing)
    : AudioProcessingSimulator(settings, std::move(audio_processing)) {
  if (settings_.call_order_input_filename) {
    call_chain_ = WavBasedSimulator::GetCustomEventChain(
        *settings_.call_order_input_filename);
  } else {
    call_chain_ = WavBasedSimulator::GetDefaultEventChain();
  }
}

WavBasedSimulator::~WavBasedSimulator() = default;

std::vector<WavBasedSimulator::SimulationEventType>
WavBasedSimulator::GetDefaultEventChain() {
  std::vector<WavBasedSimulator::SimulationEventType> call_chain(2);
  call_chain[0] = SimulationEventType::kProcessStream;
  call_chain[1] = SimulationEventType::kProcessReverseStream;
  return call_chain;
}

void WavBasedSimulator::PrepareProcessStreamCall() {
  if (settings_.fixed_interface) {
    fwd_frame_.CopyFrom(*in_buf_);
  }
  ap_->set_stream_key_pressed(settings_.override_key_pressed.value_or(false));

  if (!settings_.use_stream_delay || *settings_.use_stream_delay) {
    RTC_CHECK_EQ(AudioProcessing::kNoError,
                 ap_->set_stream_delay_ms(
                     settings_.stream_delay ? *settings_.stream_delay : 0));
  }
}

void WavBasedSimulator::PrepareReverseProcessStreamCall() {
  if (settings_.fixed_interface) {
    rev_frame_.CopyFrom(*reverse_in_buf_);
  }
}

void WavBasedSimulator::Process() {
  ConfigureAudioProcessor();

  Initialize();

  bool samples_left_to_process = true;
  int call_chain_index = 0;
  int capture_frames_since_init = 0;
  constexpr int kInitIndex = 1;
  while (samples_left_to_process) {
    switch (call_chain_[call_chain_index]) {
      case SimulationEventType::kProcessStream:
        SelectivelyToggleDataDumping(kInitIndex, capture_frames_since_init);

        samples_left_to_process = HandleProcessStreamCall();
        ++capture_frames_since_init;
        break;
      case SimulationEventType::kProcessReverseStream:
        if (settings_.reverse_input_filename) {
          samples_left_to_process = HandleProcessReverseStreamCall();
        }
        break;
      default:
        RTC_CHECK_NOTREACHED();
    }

    call_chain_index = (call_chain_index + 1) % call_chain_.size();
  }

  DetachAecDump();
}

void WavBasedSimulator::Analyze() {
  std::cout << "Inits:" << std::endl;
  std::cout << "1: -->" << std::endl;
  std::cout << " Time:" << std::endl;
  std::cout << "  Capture: 0 s (0 frames) " << std::endl;
  std::cout << "  Render: 0 s (0 frames)" << std::endl;
}

bool WavBasedSimulator::HandleProcessStreamCall() {
  bool samples_left_to_process = buffer_reader_->Read(in_buf_.get());
  if (samples_left_to_process) {
    PrepareProcessStreamCall();
    ProcessStream(settings_.fixed_interface);
  }
  return samples_left_to_process;
}

bool WavBasedSimulator::HandleProcessReverseStreamCall() {
  bool samples_left_to_process =
      reverse_buffer_reader_->Read(reverse_in_buf_.get());
  if (samples_left_to_process) {
    PrepareReverseProcessStreamCall();
    ProcessReverseStream(settings_.fixed_interface);
  }
  return samples_left_to_process;
}

void WavBasedSimulator::Initialize() {
  std::unique_ptr<WavReader> in_file(
      new WavReader(settings_.input_filename->c_str()));
  int input_sample_rate_hz = in_file->sample_rate();
  int input_num_channels = in_file->num_channels();
  buffer_reader_.reset(new ChannelBufferWavReader(std::move(in_file)));

  int output_sample_rate_hz = settings_.output_sample_rate_hz
                                  ? *settings_.output_sample_rate_hz
                                  : input_sample_rate_hz;
  int output_num_channels = settings_.output_num_channels
                                ? *settings_.output_num_channels
                                : input_num_channels;

  int reverse_sample_rate_hz = 48000;
  int reverse_num_channels = 1;
  int reverse_output_sample_rate_hz = 48000;
  int reverse_output_num_channels = 1;
  if (settings_.reverse_input_filename) {
    std::unique_ptr<WavReader> reverse_in_file(
        new WavReader(settings_.reverse_input_filename->c_str()));
    reverse_sample_rate_hz = reverse_in_file->sample_rate();
    reverse_num_channels = reverse_in_file->num_channels();
    reverse_buffer_reader_.reset(
        new ChannelBufferWavReader(std::move(reverse_in_file)));

    reverse_output_sample_rate_hz =
        settings_.reverse_output_sample_rate_hz
            ? *settings_.reverse_output_sample_rate_hz
            : reverse_sample_rate_hz;
    reverse_output_num_channels = settings_.reverse_output_num_channels
                                      ? *settings_.reverse_output_num_channels
                                      : reverse_num_channels;
  }

  SetupBuffersConfigsOutputs(
      input_sample_rate_hz, output_sample_rate_hz, reverse_sample_rate_hz,
      reverse_output_sample_rate_hz, input_num_channels, output_num_channels,
      reverse_num_channels, reverse_output_num_channels);
}

}  // namespace test
}  // namespace webrtc
