/*
 *  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 <deque>
#include <limits>
#include <string>
#include <tuple>

#include "absl/memory/memory.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_legacy.h"
#include "logging/rtc_event_log/encoder/rtc_event_log_encoder_new_format.h"
#include "logging/rtc_event_log/events/rtc_event_alr_state.h"
#include "logging/rtc_event_log/events/rtc_event_audio_network_adaptation.h"
#include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
#include "logging/rtc_event_log/events/rtc_event_audio_receive_stream_config.h"
#include "logging/rtc_event_log/events/rtc_event_audio_send_stream_config.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_delay_based.h"
#include "logging/rtc_event_log/events/rtc_event_bwe_update_loss_based.h"
#include "logging/rtc_event_log/events/rtc_event_probe_cluster_created.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_failure.h"
#include "logging/rtc_event_log/events/rtc_event_probe_result_success.h"
#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_incoming.h"
#include "logging/rtc_event_log/events/rtc_event_rtcp_packet_outgoing.h"
#include "logging/rtc_event_log/events/rtc_event_rtp_packet_incoming.h"
#include "logging/rtc_event_log/events/rtc_event_rtp_packet_outgoing.h"
#include "logging/rtc_event_log/events/rtc_event_video_receive_stream_config.h"
#include "logging/rtc_event_log/events/rtc_event_video_send_stream_config.h"
#include "logging/rtc_event_log/rtc_event_log_parser_new.h"
#include "logging/rtc_event_log/rtc_event_log_unittest_helper.h"
#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
#include "modules/remote_bitrate_estimator/include/bwe_defines.h"
#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
#include "rtc_base/random.h"
#include "test/gtest.h"

namespace webrtc {

class RtcEventLogEncoderTest
    : public testing::TestWithParam<std::tuple<int, bool>> {
 protected:
  RtcEventLogEncoderTest()
      : seed_(std::get<0>(GetParam())), prng_(seed_), gen_(seed_ * 880001UL) {
    if (std::get<1>(GetParam()))
      encoder_ = absl::make_unique<RtcEventLogEncoderNewFormat>();
    else
      encoder_ = absl::make_unique<RtcEventLogEncoderLegacy>();
  }
  ~RtcEventLogEncoderTest() override = default;

  // ANA events have some optional fields, so we want to make sure that we get
  // correct behavior both when all of the values are there, as well as when
  // only some.
  void TestRtcEventAudioNetworkAdaptation(
      std::unique_ptr<AudioEncoderRuntimeConfig> runtime_config);

  std::deque<std::unique_ptr<RtcEvent>> history_;
  // TODO(eladalon): Once we have more than one possible encoder, parameterize
  // encoder selection.
  std::unique_ptr<RtcEventLogEncoder> encoder_;
  ParsedRtcEventLogNew parsed_log_;
  const uint64_t seed_;
  Random prng_;
  test::EventGenerator gen_;
};

TEST_P(RtcEventLogEncoderTest, RtcEventAlrState) {
  std::unique_ptr<RtcEventAlrState> event = gen_.NewAlrState();
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& alr_state_events = parsed_log_.alr_state_events();

  ASSERT_EQ(alr_state_events.size(), 1u);
  test::VerifyLoggedAlrStateEvent(*event, alr_state_events[0]);
}

void RtcEventLogEncoderTest::TestRtcEventAudioNetworkAdaptation(
    std::unique_ptr<AudioEncoderRuntimeConfig> runtime_config) {
  // This function is called repeatedly. Clear state between calls.
  history_.clear();
  auto original_runtime_config = *runtime_config;
  auto event = absl::make_unique<RtcEventAudioNetworkAdaptation>(
      std::move(runtime_config));
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& ana_configs = parsed_log_.audio_network_adaptation_events();

  ASSERT_EQ(ana_configs.size(), 1u);
  test::VerifyLoggedAudioNetworkAdaptationEvent(*event, ana_configs[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationBitrate) {
  auto runtime_config = absl::make_unique<AudioEncoderRuntimeConfig>();
  const int bitrate_bps = rtc::checked_cast<int>(
      prng_.Rand(0, std::numeric_limits<int32_t>::max()));
  runtime_config->bitrate_bps = bitrate_bps;
  TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
}

TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationFrameLength) {
  auto runtime_config = absl::make_unique<AudioEncoderRuntimeConfig>();
  const int frame_length_ms = prng_.Rand(1, 1000);
  runtime_config->frame_length_ms = frame_length_ms;
  TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
}

TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationPacketLoss) {
  // To simplify the test, we just check powers of two.
  const float plr = std::pow(0.5f, prng_.Rand(1, 8));
  auto runtime_config = absl::make_unique<AudioEncoderRuntimeConfig>();
  runtime_config->uplink_packet_loss_fraction = plr;
  TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
}

TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationFec) {
  // The test might be trivially passing for one of the two boolean values, so
  // for safety's sake, we test both.
  for (bool fec_enabled : {false, true}) {
    auto runtime_config = absl::make_unique<AudioEncoderRuntimeConfig>();
    runtime_config->enable_fec = fec_enabled;
    TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
  }
}

TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationDtx) {
  // The test might be trivially passing for one of the two boolean values, so
  // for safety's sake, we test both.
  for (bool dtx_enabled : {false, true}) {
    auto runtime_config = absl::make_unique<AudioEncoderRuntimeConfig>();
    runtime_config->enable_dtx = dtx_enabled;
    TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
  }
}

TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationChannels) {
  // The test might be trivially passing for one of the two possible values, so
  // for safety's sake, we test both.
  for (size_t channels : {1, 2}) {
    auto runtime_config = absl::make_unique<AudioEncoderRuntimeConfig>();
    runtime_config->num_channels = channels;
    TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
  }
}

TEST_P(RtcEventLogEncoderTest, RtcEventAudioNetworkAdaptationAll) {
  const int bitrate_bps = rtc::checked_cast<int>(
      prng_.Rand(0, std::numeric_limits<int32_t>::max()));
  const int frame_length_ms = prng_.Rand(1, 1000);
  const float plr = std::pow(0.5f, prng_.Rand(1, 8));
  for (bool fec_enabled : {false, true}) {
    for (bool dtx_enabled : {false, true}) {
      for (size_t channels : {1, 2}) {
        auto runtime_config = absl::make_unique<AudioEncoderRuntimeConfig>();
        runtime_config->bitrate_bps = bitrate_bps;
        runtime_config->frame_length_ms = frame_length_ms;
        runtime_config->uplink_packet_loss_fraction = plr;
        runtime_config->enable_fec = fec_enabled;
        runtime_config->enable_dtx = dtx_enabled;
        runtime_config->num_channels = channels;

        TestRtcEventAudioNetworkAdaptation(std::move(runtime_config));
      }
    }
  }
}

TEST_P(RtcEventLogEncoderTest, RtcEventAudioPlayout) {
  uint32_t ssrc = prng_.Rand<uint32_t>();
  std::unique_ptr<RtcEventAudioPlayout> event = gen_.NewAudioPlayout(ssrc);
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));

  const auto& playout_events = parsed_log_.audio_playout_events();
  ASSERT_EQ(playout_events.size(), 1u);
  const auto playout_stream = playout_events.find(ssrc);
  ASSERT_TRUE(playout_stream != playout_events.end());

  ASSERT_EQ(playout_stream->second.size(), 1u);
  LoggedAudioPlayoutEvent playout_event = playout_stream->second[0];
  test::VerifyLoggedAudioPlayoutEvent(*event, playout_event);
}

TEST_P(RtcEventLogEncoderTest, RtcEventAudioReceiveStreamConfig) {
  uint32_t ssrc = prng_.Rand<uint32_t>();
  RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
  std::unique_ptr<RtcEventAudioReceiveStreamConfig> event =
      gen_.NewAudioReceiveStreamConfig(ssrc, extensions);
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& audio_recv_configs = parsed_log_.audio_recv_configs();

  ASSERT_EQ(audio_recv_configs.size(), 1u);
  test::VerifyLoggedAudioRecvConfig(*event, audio_recv_configs[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventAudioSendStreamConfig) {
  uint32_t ssrc = prng_.Rand<uint32_t>();
  RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
  std::unique_ptr<RtcEventAudioSendStreamConfig> event =
      gen_.NewAudioSendStreamConfig(ssrc, extensions);
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& audio_send_configs = parsed_log_.audio_send_configs();

  ASSERT_EQ(audio_send_configs.size(), 1u);
  test::VerifyLoggedAudioSendConfig(*event, audio_send_configs[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateDelayBased) {
  std::unique_ptr<RtcEventBweUpdateDelayBased> event =
      gen_.NewBweUpdateDelayBased();
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& bwe_delay_updates = parsed_log_.bwe_delay_updates();

  ASSERT_EQ(bwe_delay_updates.size(), 1u);
  test::VerifyLoggedBweDelayBasedUpdate(*event, bwe_delay_updates[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventBweUpdateLossBased) {
  std::unique_ptr<RtcEventBweUpdateLossBased> event =
      gen_.NewBweUpdateLossBased();
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& bwe_loss_updates = parsed_log_.bwe_loss_updates();

  ASSERT_EQ(bwe_loss_updates.size(), 1u);
  test::VerifyLoggedBweLossBasedUpdate(*event, bwe_loss_updates[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventIceCandidatePairConfig) {
  std::unique_ptr<RtcEventIceCandidatePairConfig> event =
      gen_.NewIceCandidatePairConfig();
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& ice_candidate_pair_configs =
      parsed_log_.ice_candidate_pair_configs();

  ASSERT_EQ(ice_candidate_pair_configs.size(), 1u);
  test::VerifyLoggedIceCandidatePairConfig(*event,
                                           ice_candidate_pair_configs[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventIceCandidatePair) {
  std::unique_ptr<RtcEventIceCandidatePair> event = gen_.NewIceCandidatePair();
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& ice_candidate_pair_events =
      parsed_log_.ice_candidate_pair_events();

  ASSERT_EQ(ice_candidate_pair_events.size(), 1u);
  test::VerifyLoggedIceCandidatePairEvent(*event, ice_candidate_pair_events[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStarted) {
  const int64_t timestamp_us = rtc::TimeMicros();

  ASSERT_TRUE(parsed_log_.ParseString(encoder_->EncodeLogStart(timestamp_us)));
  const auto& start_log_events = parsed_log_.start_log_events();

  ASSERT_EQ(start_log_events.size(), 1u);
  test::VerifyLoggedStartEvent(timestamp_us, start_log_events[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventLoggingStopped) {
  const int64_t timestamp_us = rtc::TimeMicros();

  ASSERT_TRUE(parsed_log_.ParseString(encoder_->EncodeLogEnd(timestamp_us)));
  const auto& stop_log_events = parsed_log_.stop_log_events();

  ASSERT_EQ(stop_log_events.size(), 1u);
  test::VerifyLoggedStopEvent(timestamp_us, stop_log_events[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventProbeClusterCreated) {
  std::unique_ptr<RtcEventProbeClusterCreated> event =
      gen_.NewProbeClusterCreated();
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& bwe_probe_cluster_created_events =
      parsed_log_.bwe_probe_cluster_created_events();

  ASSERT_EQ(bwe_probe_cluster_created_events.size(), 1u);
  test::VerifyLoggedBweProbeClusterCreatedEvent(
      *event, bwe_probe_cluster_created_events[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventProbeResultFailure) {
  std::unique_ptr<RtcEventProbeResultFailure> event =
      gen_.NewProbeResultFailure();
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& bwe_probe_failure_events = parsed_log_.bwe_probe_failure_events();

  ASSERT_EQ(bwe_probe_failure_events.size(), 1u);
  test::VerifyLoggedBweProbeFailureEvent(*event, bwe_probe_failure_events[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventProbeResultSuccess) {
  std::unique_ptr<RtcEventProbeResultSuccess> event =
      gen_.NewProbeResultSuccess();
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& bwe_probe_success_events = parsed_log_.bwe_probe_success_events();

  ASSERT_EQ(bwe_probe_success_events.size(), 1u);
  test::VerifyLoggedBweProbeSuccessEvent(*event, bwe_probe_success_events[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketIncoming) {
  std::unique_ptr<RtcEventRtcpPacketIncoming> event =
      gen_.NewRtcpPacketIncoming();
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& incoming_rtcp_packets = parsed_log_.incoming_rtcp_packets();

  ASSERT_EQ(incoming_rtcp_packets.size(), 1u);

  test::VerifyLoggedRtcpPacketIncoming(*event, incoming_rtcp_packets[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventRtcpPacketOutgoing) {
  std::unique_ptr<RtcEventRtcpPacketOutgoing> event =
      gen_.NewRtcpPacketOutgoing();
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& outgoing_rtcp_packets = parsed_log_.outgoing_rtcp_packets();

  ASSERT_EQ(outgoing_rtcp_packets.size(), 1u);

  test::VerifyLoggedRtcpPacketOutgoing(*event, outgoing_rtcp_packets[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventRtpPacketIncoming) {
  uint32_t ssrc = prng_.Rand<uint32_t>();
  RtpHeaderExtensionMap extension_map;  // TODO(terelius): Test extensions too.
  std::unique_ptr<RtcEventRtpPacketIncoming> event =
      gen_.NewRtpPacketIncoming(ssrc, extension_map);
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& incoming_rtp_packets_by_ssrc =
      parsed_log_.incoming_rtp_packets_by_ssrc();

  ASSERT_EQ(incoming_rtp_packets_by_ssrc.size(), 1u);
  const auto& stream = incoming_rtp_packets_by_ssrc[0];
  EXPECT_EQ(stream.ssrc, ssrc);
  ASSERT_EQ(stream.incoming_packets.size(), 1u);

  test::VerifyLoggedRtpPacketIncoming(*event, stream.incoming_packets[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventRtpPacketOutgoing) {
  uint32_t ssrc = prng_.Rand<uint32_t>();
  RtpHeaderExtensionMap extension_map;  // TODO(terelius): Test extensions too.
  std::unique_ptr<RtcEventRtpPacketOutgoing> event =
      gen_.NewRtpPacketOutgoing(ssrc, extension_map);
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& outgoing_rtp_packets_by_ssrc =
      parsed_log_.outgoing_rtp_packets_by_ssrc();

  ASSERT_EQ(outgoing_rtp_packets_by_ssrc.size(), 1u);
  const auto& stream = outgoing_rtp_packets_by_ssrc[0];
  EXPECT_EQ(stream.ssrc, ssrc);
  ASSERT_EQ(stream.outgoing_packets.size(), 1u);

  test::VerifyLoggedRtpPacketOutgoing(*event, stream.outgoing_packets[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventVideoReceiveStreamConfig) {
  uint32_t ssrc = prng_.Rand<uint32_t>();
  RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
  std::unique_ptr<RtcEventVideoReceiveStreamConfig> event =
      gen_.NewVideoReceiveStreamConfig(ssrc, extensions);
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& video_recv_configs = parsed_log_.video_recv_configs();

  ASSERT_EQ(video_recv_configs.size(), 1u);
  test::VerifyLoggedVideoRecvConfig(*event, video_recv_configs[0]);
}

TEST_P(RtcEventLogEncoderTest, RtcEventVideoSendStreamConfig) {
  uint32_t ssrc = prng_.Rand<uint32_t>();
  RtpHeaderExtensionMap extensions = gen_.NewRtpHeaderExtensionMap();
  std::unique_ptr<RtcEventVideoSendStreamConfig> event =
      gen_.NewVideoSendStreamConfig(ssrc, extensions);
  history_.push_back(event->Copy());

  std::string encoded = encoder_->EncodeBatch(history_.begin(), history_.end());
  ASSERT_TRUE(parsed_log_.ParseString(encoded));
  const auto& video_send_configs = parsed_log_.video_send_configs();

  ASSERT_EQ(video_send_configs.size(), 1u);
  test::VerifyLoggedVideoSendConfig(*event, video_send_configs[0]);
}

INSTANTIATE_TEST_CASE_P(RandomSeeds,
                        RtcEventLogEncoderTest,
                        ::testing::Combine(::testing::Values(1, 2, 3, 4, 5),
                                           ::testing::Bool()));

}  // namespace webrtc
