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

#include <utility>
#include <vector>

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

namespace webrtc {
namespace webrtc_pc_e2e {

using ::webrtc::test::ImprovementDirection;
using ::webrtc::test::Unit;

CrossMediaMetricsReporter::CrossMediaMetricsReporter(
    test::MetricsLogger* metrics_logger)
    : metrics_logger_(metrics_logger) {
  RTC_CHECK(metrics_logger_);
}

void CrossMediaMetricsReporter::Start(
    absl::string_view test_case_name,
    const TrackIdStreamInfoMap* reporter_helper) {
  test_case_name_ = std::string(test_case_name);
  reporter_helper_ = reporter_helper;
}

void CrossMediaMetricsReporter::OnStatsReports(
    absl::string_view pc_label,
    const rtc::scoped_refptr<const RTCStatsReport>& report) {
  auto inbound_stats = report->GetStatsOfType<RTCInboundRtpStreamStats>();
  std::map<std::string, std::vector<const RTCInboundRtpStreamStats*>>
      sync_group_stats;
  for (const auto& stat : inbound_stats) {
    if (stat->estimated_playout_timestamp.value_or(0.) > 0 &&
        stat->track_identifier.has_value()) {
      sync_group_stats[reporter_helper_
                           ->GetStreamInfoFromTrackId(*stat->track_identifier)
                           .sync_group]
          .push_back(stat);
    }
  }

  MutexLock lock(&mutex_);
  for (const auto& pair : sync_group_stats) {
    // If there is less than two streams, it is not a sync group.
    if (pair.second.size() < 2) {
      continue;
    }
    auto sync_group = std::string(pair.first);
    const RTCInboundRtpStreamStats* audio_stat = pair.second[0];
    const RTCInboundRtpStreamStats* video_stat = pair.second[1];

    RTC_CHECK(pair.second.size() == 2 && audio_stat->kind.has_value() &&
              video_stat->kind.has_value() &&
              *audio_stat->kind != *video_stat->kind)
        << "Sync group should consist of one audio and one video stream.";

    if (*audio_stat->kind == "video") {
      std::swap(audio_stat, video_stat);
    }
    // Stream labels of a sync group are same for all polls, so we need it add
    // it only once.
    if (stats_info_.find(sync_group) == stats_info_.end()) {
      RTC_CHECK(audio_stat->track_identifier.has_value());
      RTC_CHECK(video_stat->track_identifier.has_value());
      stats_info_[sync_group].audio_stream_info =
          reporter_helper_->GetStreamInfoFromTrackId(
              *audio_stat->track_identifier);
      stats_info_[sync_group].video_stream_info =
          reporter_helper_->GetStreamInfoFromTrackId(
              *video_stat->track_identifier);
    }

    double audio_video_playout_diff = *audio_stat->estimated_playout_timestamp -
                                      *video_stat->estimated_playout_timestamp;
    if (audio_video_playout_diff > 0) {
      stats_info_[sync_group].audio_ahead_ms.AddSample(
          audio_video_playout_diff);
      stats_info_[sync_group].video_ahead_ms.AddSample(0);
    } else {
      stats_info_[sync_group].audio_ahead_ms.AddSample(0);
      stats_info_[sync_group].video_ahead_ms.AddSample(
          std::abs(audio_video_playout_diff));
    }
  }
}

void CrossMediaMetricsReporter::StopAndReportResults() {
  MutexLock lock(&mutex_);
  for (const auto& pair : stats_info_) {
    const std::string& sync_group = pair.first;
    // TODO(bugs.webrtc.org/14757): Remove kExperimentalTestNameMetadataKey.
    std::map<std::string, std::string> audio_metric_metadata{
        {MetricMetadataKey::kPeerSyncGroupMetadataKey, sync_group},
        {MetricMetadataKey::kAudioStreamMetadataKey,
         pair.second.audio_stream_info.stream_label},
        {MetricMetadataKey::kPeerMetadataKey,
         pair.second.audio_stream_info.receiver_peer},
        {MetricMetadataKey::kReceiverMetadataKey,
         pair.second.audio_stream_info.receiver_peer},
        {MetricMetadataKey::kExperimentalTestNameMetadataKey, test_case_name_}};
    metrics_logger_->LogMetric(
        "audio_ahead_ms",
        GetTestCaseName(pair.second.audio_stream_info.stream_label, sync_group),
        pair.second.audio_ahead_ms, Unit::kMilliseconds,
        webrtc::test::ImprovementDirection::kSmallerIsBetter,
        std::move(audio_metric_metadata));

    // TODO(bugs.webrtc.org/14757): Remove kExperimentalTestNameMetadataKey.
    std::map<std::string, std::string> video_metric_metadata{
        {MetricMetadataKey::kPeerSyncGroupMetadataKey, sync_group},
        {MetricMetadataKey::kAudioStreamMetadataKey,
         pair.second.video_stream_info.stream_label},
        {MetricMetadataKey::kPeerMetadataKey,
         pair.second.video_stream_info.receiver_peer},
        {MetricMetadataKey::kReceiverMetadataKey,
         pair.second.video_stream_info.receiver_peer},
        {MetricMetadataKey::kExperimentalTestNameMetadataKey, test_case_name_}};
    metrics_logger_->LogMetric(
        "video_ahead_ms",
        GetTestCaseName(pair.second.video_stream_info.stream_label, sync_group),
        pair.second.video_ahead_ms, Unit::kMilliseconds,
        webrtc::test::ImprovementDirection::kSmallerIsBetter,
        std::move(video_metric_metadata));
  }
}

std::string CrossMediaMetricsReporter::GetTestCaseName(
    const std::string& stream_label,
    const std::string& sync_group) const {
  return test_case_name_ + "/" + sync_group + "_" + stream_label;
}

}  // namespace webrtc_pc_e2e
}  // namespace webrtc
