/*
 *  Copyright (c) 2019 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/audio/default_audio_quality_analyzer.h"

#include "api/stats/rtc_stats.h"
#include "api/stats/rtcstats_objects.h"
#include "api/test/metrics/metric.h"
#include "api/test/track_id_stream_info_map.h"
#include "rtc_base/checks.h"
#include "rtc_base/logging.h"
#include "test/pc/e2e/metric_metadata_keys.h"

namespace webrtc {
namespace webrtc_pc_e2e {

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

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

void DefaultAudioQualityAnalyzer::Start(std::string test_case_name,
                                        TrackIdStreamInfoMap* analyzer_helper) {
  test_case_name_ = std::move(test_case_name);
  analyzer_helper_ = analyzer_helper;
}

void DefaultAudioQualityAnalyzer::OnStatsReports(
    absl::string_view pc_label,
    const rtc::scoped_refptr<const RTCStatsReport>& report) {
  auto stats = report->GetStatsOfType<RTCInboundRtpStreamStats>();

  for (auto& stat : stats) {
    if (!stat->kind.has_value() || !(*stat->kind == "audio")) {
      continue;
    }

    StatsSample sample;
    sample.total_samples_received = stat->total_samples_received.value_or(0ul);
    sample.concealed_samples = stat->concealed_samples.value_or(0ul);
    sample.removed_samples_for_acceleration =
        stat->removed_samples_for_acceleration.value_or(0ul);
    sample.inserted_samples_for_deceleration =
        stat->inserted_samples_for_deceleration.value_or(0ul);
    sample.silent_concealed_samples =
        stat->silent_concealed_samples.value_or(0ul);
    sample.jitter_buffer_delay =
        TimeDelta::Seconds(stat->jitter_buffer_delay.value_or(0.));
    sample.jitter_buffer_target_delay =
        TimeDelta::Seconds(stat->jitter_buffer_target_delay.value_or(0.));
    sample.jitter_buffer_emitted_count =
        stat->jitter_buffer_emitted_count.value_or(0ul);
    sample.total_samples_duration = stat->total_samples_duration.value_or(0.);
    sample.total_audio_energy = stat->total_audio_energy.value_or(0.);

    TrackIdStreamInfoMap::StreamInfo stream_info =
        analyzer_helper_->GetStreamInfoFromTrackId(*stat->track_identifier);

    MutexLock lock(&lock_);
    stream_info_.emplace(stream_info.stream_label, stream_info);
    StatsSample prev_sample = last_stats_sample_[stream_info.stream_label];
    RTC_CHECK_GE(sample.total_samples_received,
                 prev_sample.total_samples_received);
    double total_samples_diff = static_cast<double>(
        sample.total_samples_received - prev_sample.total_samples_received);
    if (total_samples_diff == 0) {
      return;
    }

    AudioStreamStats& audio_stream_stats =
        streams_stats_[stream_info.stream_label];
    audio_stream_stats.expand_rate.AddSample(
        (sample.concealed_samples - prev_sample.concealed_samples) /
        total_samples_diff);
    audio_stream_stats.accelerate_rate.AddSample(
        (sample.removed_samples_for_acceleration -
         prev_sample.removed_samples_for_acceleration) /
        total_samples_diff);
    audio_stream_stats.preemptive_rate.AddSample(
        (sample.inserted_samples_for_deceleration -
         prev_sample.inserted_samples_for_deceleration) /
        total_samples_diff);

    int64_t speech_concealed_samples =
        sample.concealed_samples - sample.silent_concealed_samples;
    int64_t prev_speech_concealed_samples =
        prev_sample.concealed_samples - prev_sample.silent_concealed_samples;
    audio_stream_stats.speech_expand_rate.AddSample(
        (speech_concealed_samples - prev_speech_concealed_samples) /
        total_samples_diff);

    int64_t jitter_buffer_emitted_count_diff =
        sample.jitter_buffer_emitted_count -
        prev_sample.jitter_buffer_emitted_count;
    if (jitter_buffer_emitted_count_diff > 0) {
      TimeDelta jitter_buffer_delay_diff =
          sample.jitter_buffer_delay - prev_sample.jitter_buffer_delay;
      TimeDelta jitter_buffer_target_delay_diff =
          sample.jitter_buffer_target_delay -
          prev_sample.jitter_buffer_target_delay;
      audio_stream_stats.average_jitter_buffer_delay_ms.AddSample(
          jitter_buffer_delay_diff.ms<double>() /
          jitter_buffer_emitted_count_diff);
      audio_stream_stats.preferred_buffer_size_ms.AddSample(
          jitter_buffer_target_delay_diff.ms<double>() /
          jitter_buffer_emitted_count_diff);
    }
    audio_stream_stats.energy.AddSample(sqrt(
        (sample.total_audio_energy - prev_sample.total_audio_energy) /
        (sample.total_samples_duration - prev_sample.total_samples_duration)));

    last_stats_sample_[stream_info.stream_label] = sample;
  }
}

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

void DefaultAudioQualityAnalyzer::Stop() {
  MutexLock lock(&lock_);
  for (auto& item : streams_stats_) {
    const TrackIdStreamInfoMap::StreamInfo& stream_info =
        stream_info_[item.first];
    // TODO(bugs.webrtc.org/14757): Remove kExperimentalTestNameMetadataKey.
    std::map<std::string, std::string> metric_metadata{
        {MetricMetadataKey::kAudioStreamMetadataKey, item.first},
        {MetricMetadataKey::kPeerMetadataKey, stream_info.receiver_peer},
        {MetricMetadataKey::kReceiverMetadataKey, stream_info.receiver_peer},
        {MetricMetadataKey::kExperimentalTestNameMetadataKey, test_case_name_}};

    metrics_logger_->LogMetric("expand_rate", GetTestCaseName(item.first),
                               item.second.expand_rate, Unit::kUnitless,
                               ImprovementDirection::kSmallerIsBetter,
                               metric_metadata);
    metrics_logger_->LogMetric("accelerate_rate", GetTestCaseName(item.first),
                               item.second.accelerate_rate, Unit::kUnitless,
                               ImprovementDirection::kSmallerIsBetter,
                               metric_metadata);
    metrics_logger_->LogMetric("preemptive_rate", GetTestCaseName(item.first),
                               item.second.preemptive_rate, Unit::kUnitless,
                               ImprovementDirection::kSmallerIsBetter,
                               metric_metadata);
    metrics_logger_->LogMetric(
        "speech_expand_rate", GetTestCaseName(item.first),
        item.second.speech_expand_rate, Unit::kUnitless,
        ImprovementDirection::kSmallerIsBetter, metric_metadata);
    metrics_logger_->LogMetric(
        "average_jitter_buffer_delay_ms", GetTestCaseName(item.first),
        item.second.average_jitter_buffer_delay_ms, Unit::kMilliseconds,
        ImprovementDirection::kNeitherIsBetter, metric_metadata);
    metrics_logger_->LogMetric(
        "preferred_buffer_size_ms", GetTestCaseName(item.first),
        item.second.preferred_buffer_size_ms, Unit::kMilliseconds,
        ImprovementDirection::kNeitherIsBetter, metric_metadata);
    metrics_logger_->LogMetric("energy", GetTestCaseName(item.first),
                               item.second.energy, Unit::kUnitless,
                               ImprovementDirection::kNeitherIsBetter,
                               metric_metadata);
  }
}

std::map<std::string, AudioStreamStats>
DefaultAudioQualityAnalyzer::GetAudioStreamsStats() const {
  MutexLock lock(&lock_);
  return streams_stats_;
}

}  // namespace webrtc_pc_e2e
}  // namespace webrtc
