/*
 *  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/debug_dump_replayer.h"

#include "modules/audio_processing/test/audio_processing_builder_for_testing.h"
#include "modules/audio_processing/test/protobuf_utils.h"
#include "modules/audio_processing/test/runtime_setting_util.h"
#include "rtc_base/checks.h"

namespace webrtc {
namespace test {

namespace {

void MaybeResetBuffer(std::unique_ptr<ChannelBuffer<float>>* buffer,
                      const StreamConfig& config) {
  auto& buffer_ref = *buffer;
  if (!buffer_ref.get() || buffer_ref->num_frames() != config.num_frames() ||
      buffer_ref->num_channels() != config.num_channels()) {
    buffer_ref.reset(
        new ChannelBuffer<float>(config.num_frames(), config.num_channels()));
  }
}

}  // namespace

DebugDumpReplayer::DebugDumpReplayer()
    : input_(nullptr),  // will be created upon usage.
      reverse_(nullptr),
      output_(nullptr),
      apm_(nullptr),
      debug_file_(nullptr) {}

DebugDumpReplayer::~DebugDumpReplayer() {
  if (debug_file_)
    fclose(debug_file_);
}

bool DebugDumpReplayer::SetDumpFile(const std::string& filename) {
  debug_file_ = fopen(filename.c_str(), "rb");
  LoadNextMessage();
  return debug_file_;
}

// Get next event that has not run.
absl::optional<audioproc::Event> DebugDumpReplayer::GetNextEvent() const {
  if (!has_next_event_)
    return absl::nullopt;
  else
    return next_event_;
}

// Run the next event. Returns the event type.
bool DebugDumpReplayer::RunNextEvent() {
  if (!has_next_event_)
    return false;
  switch (next_event_.type()) {
    case audioproc::Event::INIT:
      OnInitEvent(next_event_.init());
      break;
    case audioproc::Event::STREAM:
      OnStreamEvent(next_event_.stream());
      break;
    case audioproc::Event::REVERSE_STREAM:
      OnReverseStreamEvent(next_event_.reverse_stream());
      break;
    case audioproc::Event::CONFIG:
      OnConfigEvent(next_event_.config());
      break;
    case audioproc::Event::RUNTIME_SETTING:
      OnRuntimeSettingEvent(next_event_.runtime_setting());
      break;
    case audioproc::Event::UNKNOWN_EVENT:
      // We do not expect to receive UNKNOWN event.
      RTC_CHECK_NOTREACHED();
  }
  LoadNextMessage();
  return true;
}

const ChannelBuffer<float>* DebugDumpReplayer::GetOutput() const {
  return output_.get();
}

StreamConfig DebugDumpReplayer::GetOutputConfig() const {
  return output_config_;
}

// OnInitEvent reset the input/output/reserve channel format.
void DebugDumpReplayer::OnInitEvent(const audioproc::Init& msg) {
  RTC_CHECK(msg.has_num_input_channels());
  RTC_CHECK(msg.has_output_sample_rate());
  RTC_CHECK(msg.has_num_output_channels());
  RTC_CHECK(msg.has_reverse_sample_rate());
  RTC_CHECK(msg.has_num_reverse_channels());

  input_config_ = StreamConfig(msg.sample_rate(), msg.num_input_channels());
  output_config_ =
      StreamConfig(msg.output_sample_rate(), msg.num_output_channels());
  reverse_config_ =
      StreamConfig(msg.reverse_sample_rate(), msg.num_reverse_channels());

  MaybeResetBuffer(&input_, input_config_);
  MaybeResetBuffer(&output_, output_config_);
  MaybeResetBuffer(&reverse_, reverse_config_);
}

// OnStreamEvent replays an input signal and verifies the output.
void DebugDumpReplayer::OnStreamEvent(const audioproc::Stream& msg) {
  // APM should have been created.
  RTC_CHECK(apm_.get());

  apm_->set_stream_analog_level(msg.level());
  RTC_CHECK_EQ(AudioProcessing::kNoError,
               apm_->set_stream_delay_ms(msg.delay()));

  if (msg.has_keypress()) {
    apm_->set_stream_key_pressed(msg.keypress());
  } else {
    apm_->set_stream_key_pressed(true);
  }

  RTC_CHECK_EQ(input_config_.num_channels(),
               static_cast<size_t>(msg.input_channel_size()));
  RTC_CHECK_EQ(input_config_.num_frames() * sizeof(float),
               msg.input_channel(0).size());

  for (int i = 0; i < msg.input_channel_size(); ++i) {
    memcpy(input_->channels()[i], msg.input_channel(i).data(),
           msg.input_channel(i).size());
  }

  RTC_CHECK_EQ(AudioProcessing::kNoError,
               apm_->ProcessStream(input_->channels(), input_config_,
                                   output_config_, output_->channels()));
}

void DebugDumpReplayer::OnReverseStreamEvent(
    const audioproc::ReverseStream& msg) {
  // APM should have been created.
  RTC_CHECK(apm_.get());

  RTC_CHECK_GT(msg.channel_size(), 0);
  RTC_CHECK_EQ(reverse_config_.num_channels(),
               static_cast<size_t>(msg.channel_size()));
  RTC_CHECK_EQ(reverse_config_.num_frames() * sizeof(float),
               msg.channel(0).size());

  for (int i = 0; i < msg.channel_size(); ++i) {
    memcpy(reverse_->channels()[i], msg.channel(i).data(),
           msg.channel(i).size());
  }

  RTC_CHECK_EQ(
      AudioProcessing::kNoError,
      apm_->ProcessReverseStream(reverse_->channels(), reverse_config_,
                                 reverse_config_, reverse_->channels()));
}

void DebugDumpReplayer::OnConfigEvent(const audioproc::Config& msg) {
  MaybeRecreateApm(msg);
  ConfigureApm(msg);
}

void DebugDumpReplayer::OnRuntimeSettingEvent(
    const audioproc::RuntimeSetting& msg) {
  RTC_CHECK(apm_.get());
  ReplayRuntimeSetting(apm_.get(), msg);
}

void DebugDumpReplayer::MaybeRecreateApm(const audioproc::Config& msg) {
  // These configurations cannot be changed on the fly.
  Config config;
  RTC_CHECK(msg.has_aec_delay_agnostic_enabled());
  RTC_CHECK(msg.has_aec_extended_filter_enabled());

  // We only create APM once, since changes on these fields should not
  // happen in current implementation.
  if (!apm_.get()) {
    apm_.reset(AudioProcessingBuilderForTesting().Create(config));
  }
}

void DebugDumpReplayer::ConfigureApm(const audioproc::Config& msg) {
  AudioProcessing::Config apm_config;

  // AEC2/AECM configs.
  RTC_CHECK(msg.has_aec_enabled());
  RTC_CHECK(msg.has_aecm_enabled());
  apm_config.echo_canceller.enabled = msg.aec_enabled() || msg.aecm_enabled();
  apm_config.echo_canceller.mobile_mode = msg.aecm_enabled();

  // HPF configs.
  RTC_CHECK(msg.has_hpf_enabled());
  apm_config.high_pass_filter.enabled = msg.hpf_enabled();

  // Preamp configs.
  RTC_CHECK(msg.has_pre_amplifier_enabled());
  apm_config.pre_amplifier.enabled = msg.pre_amplifier_enabled();
  apm_config.pre_amplifier.fixed_gain_factor =
      msg.pre_amplifier_fixed_gain_factor();

  // NS configs.
  RTC_CHECK(msg.has_ns_enabled());
  RTC_CHECK(msg.has_ns_level());
  apm_config.noise_suppression.enabled = msg.ns_enabled();
  apm_config.noise_suppression.level =
      static_cast<AudioProcessing::Config::NoiseSuppression::Level>(
          msg.ns_level());

  // TS configs.
  RTC_CHECK(msg.has_transient_suppression_enabled());
  apm_config.transient_suppression.enabled =
      msg.transient_suppression_enabled();

  // AGC configs.
  RTC_CHECK(msg.has_agc_enabled());
  RTC_CHECK(msg.has_agc_mode());
  RTC_CHECK(msg.has_agc_limiter_enabled());
  apm_config.gain_controller1.enabled = msg.agc_enabled();
  apm_config.gain_controller1.mode =
      static_cast<AudioProcessing::Config::GainController1::Mode>(
          msg.agc_mode());
  apm_config.gain_controller1.enable_limiter = msg.agc_limiter_enabled();
  RTC_CHECK(msg.has_noise_robust_agc_enabled());
  apm_config.gain_controller1.analog_gain_controller.enabled =
      msg.noise_robust_agc_enabled();

  apm_->ApplyConfig(apm_config);
}

void DebugDumpReplayer::LoadNextMessage() {
  has_next_event_ =
      debug_file_ && ReadMessageFromFile(debug_file_, &next_event_);
}

}  // namespace test
}  // namespace webrtc
