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

namespace webrtc {
namespace webrtc_pc_e2e {

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) {
  // TODO(https://crbug.com/webrtc/11683): use "inbound-rtp" instead of "track"
  // stats when required audio metrics moved there
  auto stats = report->GetStatsOfType<RTCMediaStreamTrackStats>();

  for (auto& stat : stats) {
    if (!stat->kind.is_defined() ||
        !(*stat->kind == RTCMediaStreamTrackKind::kAudio) ||
        !*stat->remote_source) {
      continue;
    }

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

    const std::string stream_label = std::string(
        analyzer_helper_->GetStreamLabelFromTrackId(*stat->track_identifier));

    rtc::CritScope crit(&lock_);
    StatsSample prev_sample = last_stats_sample_[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_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_target_delay_diff =
          sample.jitter_buffer_target_delay -
          prev_sample.jitter_buffer_target_delay;
      audio_stream_stats.preferred_buffer_size_ms.AddSample(
          jitter_buffer_target_delay_diff.ms<double>() /
          jitter_buffer_emitted_count_diff);
    }

    last_stats_sample_[stream_label] = sample;
  }
}

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

void DefaultAudioQualityAnalyzer::Stop() {
  using ::webrtc::test::ImproveDirection;
  rtc::CritScope crit(&lock_);
  for (auto& item : streams_stats_) {
    ReportResult("expand_rate", item.first, item.second.expand_rate, "unitless",
                 ImproveDirection::kSmallerIsBetter);
    ReportResult("accelerate_rate", item.first, item.second.accelerate_rate,
                 "unitless", ImproveDirection::kSmallerIsBetter);
    ReportResult("preemptive_rate", item.first, item.second.preemptive_rate,
                 "unitless", ImproveDirection::kSmallerIsBetter);
    ReportResult("speech_expand_rate", item.first,
                 item.second.speech_expand_rate, "unitless",
                 ImproveDirection::kSmallerIsBetter);
    ReportResult("preferred_buffer_size_ms", item.first,
                 item.second.preferred_buffer_size_ms, "ms",
                 ImproveDirection::kNone);
  }
}

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

void DefaultAudioQualityAnalyzer::ReportResult(
    const std::string& metric_name,
    const std::string& stream_label,
    const SamplesStatsCounter& counter,
    const std::string& unit,
    webrtc::test::ImproveDirection improve_direction) const {
  test::PrintResultMeanAndError(
      metric_name, /*modifier=*/"", GetTestCaseName(stream_label),
      counter.IsEmpty() ? 0 : counter.GetAverage(),
      counter.IsEmpty() ? 0 : counter.GetStandardDeviation(), unit,
      /*important=*/false, improve_direction);
}

}  // namespace webrtc_pc_e2e
}  // namespace webrtc
