/*
 *  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_processing/aec3/signal_dependent_erle_estimator.h"

#include <algorithm>
#include <iostream>
#include <string>

#include "api/audio/echo_canceller3_config.h"
#include "modules/audio_processing/aec3/render_buffer.h"
#include "modules/audio_processing/aec3/render_delay_buffer.h"
#include "rtc_base/strings/string_builder.h"
#include "test/gtest.h"

namespace webrtc {

namespace {

void GetActiveFrame(std::vector<std::vector<std::vector<float>>>* x) {
  const std::array<float, kBlockSize> frame = {
      7459.88, 17209.6, 17383,   20768.9, 16816.7, 18386.3, 4492.83, 9675.85,
      6665.52, 14808.6, 9342.3,  7483.28, 19261.7, 4145.98, 1622.18, 13475.2,
      7166.32, 6856.61, 21937,   7263.14, 9569.07, 14919,   8413.32, 7551.89,
      7848.65, 6011.27, 13080.6, 15865.2, 12656,   17459.6, 4263.93, 4503.03,
      9311.79, 21095.8, 12657.9, 13906.6, 19267.2, 11338.1, 16828.9, 11501.6,
      11405,   15031.4, 14541.6, 19765.5, 18346.3, 19350.2, 3157.47, 18095.8,
      1743.68, 21328.2, 19727.5, 7295.16, 10332.4, 11055.5, 20107.4, 14708.4,
      12416.2, 16434,   2454.69, 9840.8,  6867.23, 1615.75, 6059.9,  8394.19};
  for (size_t band = 0; band < x->size(); ++band) {
    for (size_t channel = 0; channel < (*x)[band].size(); ++channel) {
      RTC_DCHECK_GE((*x)[band][channel].size(), frame.size());
      std::copy(frame.begin(), frame.end(), (*x)[band][channel].begin());
    }
  }
}

class TestInputs {
 public:
  TestInputs(const EchoCanceller3Config& cfg,
             size_t num_render_channels,
             size_t num_capture_channels);
  ~TestInputs();
  const RenderBuffer& GetRenderBuffer() { return *render_buffer_; }
  rtc::ArrayView<const float, kFftLengthBy2Plus1> GetX2() { return X2_; }
  rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> GetY2() const {
    return Y2_;
  }
  rtc::ArrayView<const std::array<float, kFftLengthBy2Plus1>> GetE2() const {
    return E2_;
  }
  rtc::ArrayView<const std::vector<std::array<float, kFftLengthBy2Plus1>>>
  GetH2() const {
    return H2_;
  }
  const std::vector<bool>& GetConvergedFilters() const {
    return converged_filters_;
  }
  void Update();

 private:
  void UpdateCurrentPowerSpectra();
  int n_ = 0;
  std::unique_ptr<RenderDelayBuffer> render_delay_buffer_;
  RenderBuffer* render_buffer_;
  std::array<float, kFftLengthBy2Plus1> X2_;
  std::vector<std::array<float, kFftLengthBy2Plus1>> Y2_;
  std::vector<std::array<float, kFftLengthBy2Plus1>> E2_;
  std::vector<std::vector<std::array<float, kFftLengthBy2Plus1>>> H2_;
  std::vector<std::vector<std::vector<float>>> x_;
  std::vector<bool> converged_filters_;
};

TestInputs::TestInputs(const EchoCanceller3Config& cfg,
                       size_t num_render_channels,
                       size_t num_capture_channels)
    : render_delay_buffer_(
          RenderDelayBuffer::Create(cfg, 16000, num_render_channels)),
      Y2_(num_capture_channels),
      E2_(num_capture_channels),
      H2_(num_capture_channels,
          std::vector<std::array<float, kFftLengthBy2Plus1>>(
              cfg.filter.refined.length_blocks)),
      x_(1,
         std::vector<std::vector<float>>(num_render_channels,
                                         std::vector<float>(kBlockSize, 0.f))),
      converged_filters_(num_capture_channels, true) {
  render_delay_buffer_->AlignFromDelay(4);
  render_buffer_ = render_delay_buffer_->GetRenderBuffer();
  for (auto& H2_ch : H2_) {
    for (auto& H2_p : H2_ch) {
      H2_p.fill(0.f);
    }
  }
  for (auto& H2_p : H2_[0]) {
    H2_p.fill(1.f);
  }
}

TestInputs::~TestInputs() = default;

void TestInputs::Update() {
  if (n_ % 2 == 0) {
    std::fill(x_[0][0].begin(), x_[0][0].end(), 0.f);
  } else {
    GetActiveFrame(&x_);
  }

  render_delay_buffer_->Insert(x_);
  render_delay_buffer_->PrepareCaptureProcessing();
  UpdateCurrentPowerSpectra();
  ++n_;
}

void TestInputs::UpdateCurrentPowerSpectra() {
  const SpectrumBuffer& spectrum_render_buffer =
      render_buffer_->GetSpectrumBuffer();
  size_t idx = render_buffer_->Position();
  size_t prev_idx = spectrum_render_buffer.OffsetIndex(idx, 1);
  auto& X2 = spectrum_render_buffer.buffer[idx][/*channel=*/0];
  auto& X2_prev = spectrum_render_buffer.buffer[prev_idx][/*channel=*/0];
  std::copy(X2.begin(), X2.end(), X2_.begin());
  for (size_t ch = 0; ch < Y2_.size(); ++ch) {
    RTC_DCHECK_EQ(X2.size(), Y2_[ch].size());
    for (size_t k = 0; k < X2.size(); ++k) {
      E2_[ch][k] = 0.01f * X2_prev[k];
      Y2_[ch][k] = X2[k] + E2_[ch][k];
    }
  }
}

}  // namespace

class SignalDependentErleEstimatorMultiChannel
    : public ::testing::Test,
      public ::testing::WithParamInterface<std::tuple<size_t, size_t>> {};

INSTANTIATE_TEST_SUITE_P(MultiChannel,
                         SignalDependentErleEstimatorMultiChannel,
                         ::testing::Combine(::testing::Values(1, 2, 4),
                                            ::testing::Values(1, 2, 4)));

TEST_P(SignalDependentErleEstimatorMultiChannel, SweepSettings) {
  const size_t num_render_channels = std::get<0>(GetParam());
  const size_t num_capture_channels = std::get<1>(GetParam());
  EchoCanceller3Config cfg;
  size_t max_length_blocks = 50;
  for (size_t blocks = 1; blocks < max_length_blocks; blocks = blocks + 10) {
    for (size_t delay_headroom = 0; delay_headroom < 5; ++delay_headroom) {
      for (size_t num_sections = 2; num_sections < max_length_blocks;
           ++num_sections) {
        cfg.filter.refined.length_blocks = blocks;
        cfg.filter.refined_initial.length_blocks =
            std::min(cfg.filter.refined_initial.length_blocks, blocks);
        cfg.delay.delay_headroom_samples = delay_headroom * kBlockSize;
        cfg.erle.num_sections = num_sections;
        if (EchoCanceller3Config::Validate(&cfg)) {
          SignalDependentErleEstimator s(cfg, num_capture_channels);
          std::vector<std::array<float, kFftLengthBy2Plus1>> average_erle(
              num_capture_channels);
          for (auto& e : average_erle) {
            e.fill(cfg.erle.max_l);
          }
          TestInputs inputs(cfg, num_render_channels, num_capture_channels);
          for (size_t n = 0; n < 10; ++n) {
            inputs.Update();
            s.Update(inputs.GetRenderBuffer(), inputs.GetH2(), inputs.GetX2(),
                     inputs.GetY2(), inputs.GetE2(), average_erle,
                     inputs.GetConvergedFilters());
          }
        }
      }
    }
  }
}

TEST_P(SignalDependentErleEstimatorMultiChannel, LongerRun) {
  const size_t num_render_channels = std::get<0>(GetParam());
  const size_t num_capture_channels = std::get<1>(GetParam());
  EchoCanceller3Config cfg;
  cfg.filter.refined.length_blocks = 2;
  cfg.filter.refined_initial.length_blocks = 1;
  cfg.delay.delay_headroom_samples = 0;
  cfg.delay.hysteresis_limit_blocks = 0;
  cfg.erle.num_sections = 2;
  EXPECT_EQ(EchoCanceller3Config::Validate(&cfg), true);
  std::vector<std::array<float, kFftLengthBy2Plus1>> average_erle(
      num_capture_channels);
  for (auto& e : average_erle) {
    e.fill(cfg.erle.max_l);
  }
  SignalDependentErleEstimator s(cfg, num_capture_channels);
  TestInputs inputs(cfg, num_render_channels, num_capture_channels);
  for (size_t n = 0; n < 200; ++n) {
    inputs.Update();
    s.Update(inputs.GetRenderBuffer(), inputs.GetH2(), inputs.GetX2(),
             inputs.GetY2(), inputs.GetE2(), average_erle,
             inputs.GetConvergedFilters());
  }
}

}  // namespace webrtc
