/*
 *  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 <utility>
#include <vector>

#include "webrtc/logging/rtc_event_log/mock/mock_rtc_event_log.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/audio_network_adaptor_impl.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_controller.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_controller_manager.h"
#include "webrtc/modules/audio_coding/audio_network_adaptor/mock/mock_debug_dump_writer.h"
#include "webrtc/rtc_base/fakeclock.h"
#include "webrtc/test/field_trial.h"
#include "webrtc/test/gtest.h"

namespace webrtc {

using ::testing::_;
using ::testing::NiceMock;
using ::testing::Return;
using ::testing::SetArgPointee;

namespace {

constexpr size_t kNumControllers = 2;

constexpr int64_t kClockInitialTimeMs = 12345678;

MATCHER_P(NetworkMetricsIs, metric, "") {
  return arg.uplink_bandwidth_bps == metric.uplink_bandwidth_bps &&
         arg.target_audio_bitrate_bps == metric.target_audio_bitrate_bps &&
         arg.rtt_ms == metric.rtt_ms &&
         arg.overhead_bytes_per_packet == metric.overhead_bytes_per_packet &&
         arg.uplink_packet_loss_fraction ==
             metric.uplink_packet_loss_fraction &&
         arg.uplink_recoverable_packet_loss_fraction ==
             metric.uplink_recoverable_packet_loss_fraction;
}

MATCHER_P(EncoderRuntimeConfigIs, config, "") {
  return arg.bitrate_bps == config.bitrate_bps &&
         arg.frame_length_ms == config.frame_length_ms &&
         arg.uplink_packet_loss_fraction ==
             config.uplink_packet_loss_fraction &&
         arg.enable_fec == config.enable_fec &&
         arg.enable_dtx == config.enable_dtx &&
         arg.num_channels == config.num_channels;
}

struct AudioNetworkAdaptorStates {
  std::unique_ptr<AudioNetworkAdaptorImpl> audio_network_adaptor;
  std::vector<std::unique_ptr<MockController>> mock_controllers;
  std::unique_ptr<MockRtcEventLog> event_log;
  MockDebugDumpWriter* mock_debug_dump_writer;
};

AudioNetworkAdaptorStates CreateAudioNetworkAdaptor() {
  AudioNetworkAdaptorStates states;
  std::vector<Controller*> controllers;
  for (size_t i = 0; i < kNumControllers; ++i) {
    auto controller =
        std::unique_ptr<MockController>(new NiceMock<MockController>());
    EXPECT_CALL(*controller, Die());
    controllers.push_back(controller.get());
    states.mock_controllers.push_back(std::move(controller));
  }

  auto controller_manager = std::unique_ptr<MockControllerManager>(
      new NiceMock<MockControllerManager>());

  EXPECT_CALL(*controller_manager, Die());
  EXPECT_CALL(*controller_manager, GetControllers())
      .WillRepeatedly(Return(controllers));
  EXPECT_CALL(*controller_manager, GetSortedControllers(_))
      .WillRepeatedly(Return(controllers));

  states.event_log.reset(new NiceMock<MockRtcEventLog>());

  auto debug_dump_writer =
      std::unique_ptr<MockDebugDumpWriter>(new NiceMock<MockDebugDumpWriter>());
  EXPECT_CALL(*debug_dump_writer, Die());
  states.mock_debug_dump_writer = debug_dump_writer.get();

  AudioNetworkAdaptorImpl::Config config;
  config.event_log = states.event_log.get();
  // AudioNetworkAdaptorImpl governs the lifetime of controller manager.
  states.audio_network_adaptor.reset(new AudioNetworkAdaptorImpl(
      config,
      std::move(controller_manager), std::move(debug_dump_writer)));

  return states;
}

void SetExpectCallToUpdateNetworkMetrics(
    const std::vector<std::unique_ptr<MockController>>& controllers,
    const Controller::NetworkMetrics& check) {
  for (auto& mock_controller : controllers) {
    EXPECT_CALL(*mock_controller,
                UpdateNetworkMetrics(NetworkMetricsIs(check)));
  }
}

}  // namespace

TEST(AudioNetworkAdaptorImplTest,
     UpdateNetworkMetricsIsCalledOnSetUplinkBandwidth) {
  auto states = CreateAudioNetworkAdaptor();
  constexpr int kBandwidth = 16000;
  Controller::NetworkMetrics check;
  check.uplink_bandwidth_bps = rtc::Optional<int>(kBandwidth);
  SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
  states.audio_network_adaptor->SetUplinkBandwidth(kBandwidth);
}

TEST(AudioNetworkAdaptorImplTest,
     UpdateNetworkMetricsIsCalledOnSetUplinkPacketLossFraction) {
  auto states = CreateAudioNetworkAdaptor();
  constexpr float kPacketLoss = 0.7f;
  Controller::NetworkMetrics check;
  check.uplink_packet_loss_fraction = rtc::Optional<float>(kPacketLoss);
  SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
  states.audio_network_adaptor->SetUplinkPacketLossFraction(kPacketLoss);
}

TEST(AudioNetworkAdaptorImplTest,
     UpdateNetworkMetricsIsCalledOnSetUplinkRecoverablePacketLossFraction) {
  auto states = CreateAudioNetworkAdaptor();
  constexpr float kRecoverablePacketLoss = 0.1f;
  Controller::NetworkMetrics check;
  check.uplink_recoverable_packet_loss_fraction =
      rtc::Optional<float>(kRecoverablePacketLoss);
  SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
  states.audio_network_adaptor->SetUplinkRecoverablePacketLossFraction(
      kRecoverablePacketLoss);
}

TEST(AudioNetworkAdaptorImplTest, UpdateNetworkMetricsIsCalledOnSetRtt) {
  auto states = CreateAudioNetworkAdaptor();
  constexpr int kRtt = 100;
  Controller::NetworkMetrics check;
  check.rtt_ms = rtc::Optional<int>(kRtt);
  SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
  states.audio_network_adaptor->SetRtt(kRtt);
}

TEST(AudioNetworkAdaptorImplTest,
     UpdateNetworkMetricsIsCalledOnSetTargetAudioBitrate) {
  auto states = CreateAudioNetworkAdaptor();
  constexpr int kTargetAudioBitrate = 15000;
  Controller::NetworkMetrics check;
  check.target_audio_bitrate_bps = rtc::Optional<int>(kTargetAudioBitrate);
  SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
  states.audio_network_adaptor->SetTargetAudioBitrate(kTargetAudioBitrate);
}

TEST(AudioNetworkAdaptorImplTest, UpdateNetworkMetricsIsCalledOnSetOverhead) {
  auto states = CreateAudioNetworkAdaptor();
  constexpr size_t kOverhead = 64;
  Controller::NetworkMetrics check;
  check.overhead_bytes_per_packet = rtc::Optional<size_t>(kOverhead);
  SetExpectCallToUpdateNetworkMetrics(states.mock_controllers, check);
  states.audio_network_adaptor->SetOverhead(kOverhead);
}

TEST(AudioNetworkAdaptorImplTest,
     MakeDecisionIsCalledOnGetEncoderRuntimeConfig) {
  auto states = CreateAudioNetworkAdaptor();
  for (auto& mock_controller : states.mock_controllers)
    EXPECT_CALL(*mock_controller, MakeDecision(_));
  states.audio_network_adaptor->GetEncoderRuntimeConfig();
}

TEST(AudioNetworkAdaptorImplTest,
     DumpEncoderRuntimeConfigIsCalledOnGetEncoderRuntimeConfig) {
  test::ScopedFieldTrials override_field_trials(
      "WebRTC-Audio-BitrateAdaptation/Enabled/WebRTC-Audio-FecAdaptation/"
      "Enabled/");
  rtc::ScopedFakeClock fake_clock;
  fake_clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kClockInitialTimeMs));
  auto states = CreateAudioNetworkAdaptor();
  AudioEncoderRuntimeConfig config;
  config.bitrate_bps = rtc::Optional<int>(32000);
  config.enable_fec = rtc::Optional<bool>(true);

  EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
      .WillOnce(SetArgPointee<0>(config));

  EXPECT_CALL(*states.mock_debug_dump_writer,
              DumpEncoderRuntimeConfig(EncoderRuntimeConfigIs(config),
                                       kClockInitialTimeMs));
  states.audio_network_adaptor->GetEncoderRuntimeConfig();
}

TEST(AudioNetworkAdaptorImplTest,
     DumpNetworkMetricsIsCalledOnSetNetworkMetrics) {
  rtc::ScopedFakeClock fake_clock;
  fake_clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(kClockInitialTimeMs));

  auto states = CreateAudioNetworkAdaptor();

  constexpr int kBandwidth = 16000;
  constexpr float kPacketLoss = 0.7f;
  const auto kRecoverablePacketLoss = 0.2f;
  constexpr int kRtt = 100;
  constexpr int kTargetAudioBitrate = 15000;
  constexpr size_t kOverhead = 64;

  Controller::NetworkMetrics check;
  check.uplink_bandwidth_bps = rtc::Optional<int>(kBandwidth);
  int64_t timestamp_check = kClockInitialTimeMs;

  EXPECT_CALL(*states.mock_debug_dump_writer,
              DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
  states.audio_network_adaptor->SetUplinkBandwidth(kBandwidth);

  fake_clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(100));
  timestamp_check += 100;
  check.uplink_packet_loss_fraction = rtc::Optional<float>(kPacketLoss);
  EXPECT_CALL(*states.mock_debug_dump_writer,
              DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
  states.audio_network_adaptor->SetUplinkPacketLossFraction(kPacketLoss);

  fake_clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(50));
  timestamp_check += 50;
  check.uplink_recoverable_packet_loss_fraction =
      rtc::Optional<float>(kRecoverablePacketLoss);
  EXPECT_CALL(*states.mock_debug_dump_writer,
              DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
  states.audio_network_adaptor->SetUplinkRecoverablePacketLossFraction(
      kRecoverablePacketLoss);

  fake_clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(200));
  timestamp_check += 200;
  check.rtt_ms = rtc::Optional<int>(kRtt);
  EXPECT_CALL(*states.mock_debug_dump_writer,
              DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
  states.audio_network_adaptor->SetRtt(kRtt);

  fake_clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(150));
  timestamp_check += 150;
  check.target_audio_bitrate_bps = rtc::Optional<int>(kTargetAudioBitrate);
  EXPECT_CALL(*states.mock_debug_dump_writer,
              DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
  states.audio_network_adaptor->SetTargetAudioBitrate(kTargetAudioBitrate);

  fake_clock.AdvanceTime(rtc::TimeDelta::FromMilliseconds(50));
  timestamp_check += 50;
  check.overhead_bytes_per_packet = rtc::Optional<size_t>(kOverhead);
  EXPECT_CALL(*states.mock_debug_dump_writer,
              DumpNetworkMetrics(NetworkMetricsIs(check), timestamp_check));
  states.audio_network_adaptor->SetOverhead(kOverhead);
}

TEST(AudioNetworkAdaptorImplTest, LogRuntimeConfigOnGetEncoderRuntimeConfig) {
  test::ScopedFieldTrials override_field_trials(
      "WebRTC-Audio-BitrateAdaptation/Enabled/WebRTC-Audio-FecAdaptation/"
      "Enabled/");
  auto states = CreateAudioNetworkAdaptor();

  AudioEncoderRuntimeConfig config;
  config.bitrate_bps = rtc::Optional<int>(32000);
  config.enable_fec = rtc::Optional<bool>(true);

  EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
      .WillOnce(SetArgPointee<0>(config));

  EXPECT_CALL(*states.event_log,
              LogAudioNetworkAdaptation(EncoderRuntimeConfigIs(config)))
      .Times(1);
  states.audio_network_adaptor->GetEncoderRuntimeConfig();
}

TEST(AudioNetworkAdaptorImplTest, TestANAStats) {
  auto states = CreateAudioNetworkAdaptor();

  // Simulate some adaptation, otherwise the stats will not show anything.
  AudioEncoderRuntimeConfig config1, config2;
  config1.bitrate_bps = rtc::Optional<int>(32000);
  config1.num_channels = rtc::Optional<size_t>(2);
  config1.enable_fec = rtc::Optional<bool>(true);
  config1.enable_dtx = rtc::Optional<bool>(true);
  config1.frame_length_ms = rtc::Optional<int>(120);
  config1.uplink_packet_loss_fraction = rtc::Optional<float>(0.1f);
  config2.bitrate_bps = rtc::Optional<int>(16000);
  config2.num_channels = rtc::Optional<size_t>(1);
  config2.enable_fec = rtc::Optional<bool>(false);
  config2.enable_dtx = rtc::Optional<bool>(false);
  config2.frame_length_ms = rtc::Optional<int>(60);
  config1.uplink_packet_loss_fraction = rtc::Optional<float>(0.1f);

  EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
      .WillOnce(SetArgPointee<0>(config1));
  states.audio_network_adaptor->GetEncoderRuntimeConfig();
  EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
      .WillOnce(SetArgPointee<0>(config2));
  states.audio_network_adaptor->GetEncoderRuntimeConfig();
  EXPECT_CALL(*states.mock_controllers[0], MakeDecision(_))
      .WillOnce(SetArgPointee<0>(config1));
  states.audio_network_adaptor->GetEncoderRuntimeConfig();

  auto ana_stats = states.audio_network_adaptor->GetStats();

  EXPECT_EQ(ana_stats.bitrate_action_counter, 2);
  EXPECT_EQ(ana_stats.channel_action_counter, 2);
  EXPECT_EQ(ana_stats.dtx_action_counter, 2);
  EXPECT_EQ(ana_stats.fec_action_counter, 2);
  EXPECT_EQ(ana_stats.frame_length_increase_counter, 1);
  EXPECT_EQ(ana_stats.frame_length_decrease_counter, 1);
  EXPECT_EQ(ana_stats.uplink_packet_loss_fraction, 0.1f);
}

}  // namespace webrtc
