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

#include <vector>

#include "absl/strings/string_view.h"

namespace {

// These characters mess with either the stdout parsing or the dashboard itself.
const std::vector<std::string>& InvalidCharacters() {
  static const std::vector<std::string> kInvalidCharacters({"/", ":", "="});

  return kInvalidCharacters;
}

void CheckForInvalidCharacters(absl::string_view str) {
  for (const auto& invalid : InvalidCharacters()) {
    RTC_CHECK(str.find(invalid) == std::string::npos)
        << "Given invalid character for perf names '" << invalid << "'";
  }
}

}  // namespace

namespace webrtc {
namespace test {

namespace {

// For now, mark all tests as "not important". This distinction mostly goes away
// in histograms anyway.
const bool kNotImportant = false;

std::string UnitToString(Unit unit) {
  // Down the line, we should convert directly from Unit to the histogram.proto
  // enum values. We need to convert to strings until all uses of perf_test.h
  // have been eliminated. We're not using the proto enum directly in the .h of
  // this file because we don't want to limit the exposure of the proto.
  //
  // Keep this list up to date with kJsonToProtoUnit in histogram.cc in the
  // Catapult repo.
  switch (unit) {
    case Unit::kMs:
      return "ms";
    case Unit::kMsBestFitFormat:
      return "msBestFitFormat";
    case Unit::kMsTs:
      return "tsMs";
    case Unit::kNPercent:
      return "n%";
    case Unit::kSizeInBytes:
      return "sizeInBytes";
    case Unit::kBytesPerSecond:
      return "bytesPerSecond";
    case Unit::kHertz:
      return "Hz";
    case Unit::kUnitless:
      return "unitless";
    case Unit::kCount:
      return "count";
    case Unit::kSigma:
      return "sigma";
    default:
      RTC_NOTREACHED() << "Unknown unit " << unit;
      return "unitless";
  }
}

}  // namespace

PerfResultReporter::PerfResultReporter(absl::string_view metric_basename,
                                       absl::string_view story_name)
    : metric_basename_(metric_basename), story_name_(story_name) {
  CheckForInvalidCharacters(metric_basename_);
  CheckForInvalidCharacters(story_name_);
}

PerfResultReporter::~PerfResultReporter() = default;

void PerfResultReporter::RegisterMetric(absl::string_view metric_suffix,
                                        Unit unit) {
  RegisterMetric(metric_suffix, unit, ImproveDirection::kNone);
}
void PerfResultReporter::RegisterMetric(absl::string_view metric_suffix,
                                        Unit unit,
                                        ImproveDirection improve_direction) {
  CheckForInvalidCharacters(metric_suffix);
  std::string metric(metric_suffix);
  RTC_CHECK(metric_map_.count(metric) == 0);
  metric_map_.insert({std::move(metric), {unit, improve_direction}});
}

void PerfResultReporter::AddResult(absl::string_view metric_suffix,
                                   size_t value) const {
  auto info = GetMetricInfoOrFail(metric_suffix);

  PrintResult(metric_basename_, metric_suffix, story_name_, value,
              UnitToString(info.unit), kNotImportant, info.improve_direction);
}

void PerfResultReporter::AddResult(absl::string_view metric_suffix,
                                   double value) const {
  auto info = GetMetricInfoOrFail(metric_suffix);

  PrintResult(metric_basename_, metric_suffix, story_name_, value,
              UnitToString(info.unit), kNotImportant, info.improve_direction);
}

void PerfResultReporter::AddResultList(
    absl::string_view metric_suffix,
    rtc::ArrayView<const double> values) const {
  auto info = GetMetricInfoOrFail(metric_suffix);

  PrintResultList(metric_basename_, metric_suffix, story_name_, values,
                  UnitToString(info.unit), kNotImportant,
                  info.improve_direction);
}

void PerfResultReporter::AddResultMeanAndError(absl::string_view metric_suffix,
                                               const double mean,
                                               const double error) {
  auto info = GetMetricInfoOrFail(metric_suffix);

  PrintResultMeanAndError(metric_basename_, metric_suffix, story_name_, mean,
                          error, UnitToString(info.unit), kNotImportant,
                          info.improve_direction);
}

absl::optional<MetricInfo> PerfResultReporter::GetMetricInfo(
    absl::string_view metric_suffix) const {
  auto iter = metric_map_.find(std::string(metric_suffix));
  if (iter == metric_map_.end()) {
    return absl::optional<MetricInfo>();
  }

  return absl::optional<MetricInfo>(iter->second);
}

MetricInfo PerfResultReporter::GetMetricInfoOrFail(
    absl::string_view metric_suffix) const {
  absl::optional<MetricInfo> info = GetMetricInfo(metric_suffix);
  RTC_CHECK(info.has_value())
      << "Attempted to use unregistered metric " << metric_suffix;
  return *info;
}

}  // namespace test
}  // namespace webrtc
