/*
 *  Copyright (c) 2020 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 "test/pc/e2e/analyzer/video/video_quality_metrics_reporter.h"

#include <map>
#include <string>

#include "api/stats/rtc_stats.h"
#include "api/stats/rtcstats_objects.h"
#include "api/test/metrics/metric.h"
#include "api/units/data_rate.h"
#include "api/units/time_delta.h"
#include "api/units/timestamp.h"
#include "rtc_base/checks.h"
#include "test/pc/e2e/metric_metadata_keys.h"

namespace webrtc {
namespace webrtc_pc_e2e {
namespace {

using ::webrtc::test::ImprovementDirection;
using ::webrtc::test::Unit;
using ::webrtc::webrtc_pc_e2e::MetricMetadataKey;

SamplesStatsCounter BytesPerSecondToKbps(const SamplesStatsCounter& counter) {
  return counter * 0.008;
}

}  // namespace

VideoQualityMetricsReporter::VideoQualityMetricsReporter(
    Clock* const clock,
    test::MetricsLogger* const metrics_logger)
    : clock_(clock), metrics_logger_(metrics_logger) {
  RTC_CHECK(metrics_logger_);
}

void VideoQualityMetricsReporter::Start(
    absl::string_view test_case_name,
    const TrackIdStreamInfoMap* /*reporter_helper*/) {
  test_case_name_ = std::string(test_case_name);
  start_time_ = Now();
}

void VideoQualityMetricsReporter::OnStatsReports(
    absl::string_view pc_label,
    const rtc::scoped_refptr<const RTCStatsReport>& report) {
  RTC_CHECK(start_time_)
      << "Please invoke Start(...) method before calling OnStatsReports(...)";

  auto transport_stats = report->GetStatsOfType<RTCTransportStats>();
  if (transport_stats.size() == 0u ||
      !transport_stats[0]->selected_candidate_pair_id.is_defined()) {
    return;
  }
  RTC_DCHECK_EQ(transport_stats.size(), 1);
  std::string selected_ice_id =
      transport_stats[0]->selected_candidate_pair_id.ValueToString();
  // Use the selected ICE candidate pair ID to get the appropriate ICE stats.
  const RTCIceCandidatePairStats ice_candidate_pair_stats =
      report->Get(selected_ice_id)->cast_to<const RTCIceCandidatePairStats>();

  auto outbound_rtp_stats = report->GetStatsOfType<RTCOutboundRtpStreamStats>();
  StatsSample sample;
  for (auto& s : outbound_rtp_stats) {
    if (!s->kind.is_defined()) {
      continue;
    }
    if (!(*s->kind == RTCMediaStreamTrackKind::kVideo)) {
      continue;
    }
    if (s->timestamp() > sample.sample_time) {
      sample.sample_time = s->timestamp();
    }
    sample.retransmitted_bytes_sent +=
        DataSize::Bytes(s->retransmitted_bytes_sent.ValueOrDefault(0ul));
    sample.bytes_sent += DataSize::Bytes(s->bytes_sent.ValueOrDefault(0ul));
    sample.header_bytes_sent +=
        DataSize::Bytes(s->header_bytes_sent.ValueOrDefault(0ul));
  }

  MutexLock lock(&video_bwe_stats_lock_);
  VideoBweStats& video_bwe_stats = video_bwe_stats_[std::string(pc_label)];
  if (ice_candidate_pair_stats.available_outgoing_bitrate.is_defined()) {
    video_bwe_stats.available_send_bandwidth.AddSample(
        DataRate::BitsPerSec(
            *ice_candidate_pair_stats.available_outgoing_bitrate)
            .bytes_per_sec());
  }

  StatsSample prev_sample = last_stats_sample_[std::string(pc_label)];
  if (prev_sample.sample_time.IsZero()) {
    prev_sample.sample_time = start_time_.value();
  }
  last_stats_sample_[std::string(pc_label)] = sample;

  TimeDelta time_between_samples = sample.sample_time - prev_sample.sample_time;
  if (time_between_samples.IsZero()) {
    return;
  }

  DataRate retransmission_bitrate =
      (sample.retransmitted_bytes_sent - prev_sample.retransmitted_bytes_sent) /
      time_between_samples;
  video_bwe_stats.retransmission_bitrate.AddSample(
      retransmission_bitrate.bytes_per_sec());
  DataRate transmission_bitrate =
      (sample.bytes_sent + sample.header_bytes_sent - prev_sample.bytes_sent -
       prev_sample.header_bytes_sent) /
      time_between_samples;
  video_bwe_stats.transmission_bitrate.AddSample(
      transmission_bitrate.bytes_per_sec());
}

void VideoQualityMetricsReporter::StopAndReportResults() {
  MutexLock video_bwemutex_(&video_bwe_stats_lock_);
  for (const auto& item : video_bwe_stats_) {
    ReportVideoBweResults(item.first, item.second);
  }
}

std::string VideoQualityMetricsReporter::GetTestCaseName(
    const std::string& peer_name) const {
  return test_case_name_ + "/" + peer_name;
}

void VideoQualityMetricsReporter::ReportVideoBweResults(
    const std::string& peer_name,
    const VideoBweStats& video_bwe_stats) {
  std::string test_case_name = GetTestCaseName(peer_name);
  // TODO(bugs.webrtc.org/14757): Remove kExperimentalTestNameMetadataKey.
  std::map<std::string, std::string> metric_metadata{
      {MetricMetadataKey::kPeerMetadataKey, peer_name},
      {MetricMetadataKey::kExperimentalTestNameMetadataKey, test_case_name_}};

  metrics_logger_->LogMetric(
      "available_send_bandwidth", test_case_name,
      BytesPerSecondToKbps(video_bwe_stats.available_send_bandwidth),
      Unit::kKilobitsPerSecond, ImprovementDirection::kNeitherIsBetter,
      metric_metadata);
  metrics_logger_->LogMetric(
      "transmission_bitrate", test_case_name,
      BytesPerSecondToKbps(video_bwe_stats.transmission_bitrate),
      Unit::kKilobitsPerSecond, ImprovementDirection::kNeitherIsBetter,
      metric_metadata);
  metrics_logger_->LogMetric(
      "retransmission_bitrate", test_case_name,
      BytesPerSecondToKbps(video_bwe_stats.retransmission_bitrate),
      Unit::kKilobitsPerSecond, ImprovementDirection::kNeitherIsBetter,
      metric_metadata);
}

}  // namespace webrtc_pc_e2e
}  // namespace webrtc
