/*
 *  Copyright (c) 2022 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 "api/test/metrics/metrics_set_proto_file_exporter.h"

#include <stdio.h>

#include <string>

#include "api/test/metrics/metric.h"
#include "rtc_base/logging.h"
#include "test/testsupport/file_utils.h"

#if WEBRTC_ENABLE_PROTOBUF
#include "api/test/metrics/proto/metric.pb.h"
#endif

namespace webrtc {
namespace test {
namespace {

#if WEBRTC_ENABLE_PROTOBUF
webrtc::test_metrics::Unit ToProtoUnit(Unit unit) {
  switch (unit) {
    case Unit::kMilliseconds:
      return webrtc::test_metrics::Unit::MILLISECONDS;
    case Unit::kPercent:
      return webrtc::test_metrics::Unit::PERCENT;
    case Unit::kBytes:
      return webrtc::test_metrics::Unit::BYTES;
    case Unit::kKilobitsPerSecond:
      return webrtc::test_metrics::Unit::KILOBITS_PER_SECOND;
    case Unit::kHertz:
      return webrtc::test_metrics::Unit::HERTZ;
    case Unit::kUnitless:
      return webrtc::test_metrics::Unit::UNITLESS;
    case Unit::kCount:
      return webrtc::test_metrics::Unit::COUNT;
  }
}

webrtc::test_metrics::ImprovementDirection ToProtoImprovementDirection(
    ImprovementDirection direction) {
  switch (direction) {
    case ImprovementDirection::kBiggerIsBetter:
      return webrtc::test_metrics::ImprovementDirection::BIGGER_IS_BETTER;
    case ImprovementDirection::kNeitherIsBetter:
      return webrtc::test_metrics::ImprovementDirection::NEITHER_IS_BETTER;
    case ImprovementDirection::kSmallerIsBetter:
      return webrtc::test_metrics::ImprovementDirection::SMALLER_IS_BETTER;
  }
}

void SetTimeSeries(
    const Metric::TimeSeries& time_series,
    webrtc::test_metrics::Metric::TimeSeries* proto_time_series) {
  for (const Metric::TimeSeries::Sample& sample : time_series.samples) {
    webrtc::test_metrics::Metric::TimeSeries::Sample* proto_sample =
        proto_time_series->add_samples();
    proto_sample->set_value(sample.value);
    proto_sample->set_timestamp_us(sample.timestamp.us());
    for (const auto& [key, value] : sample.sample_metadata) {
      proto_sample->mutable_sample_metadata()->insert({key, value});
    }
  }
}

void SetStats(const Metric::Stats& stats,
              webrtc::test_metrics::Metric::Stats* proto_stats) {
  if (stats.mean.has_value()) {
    proto_stats->set_mean(*stats.mean);
  }
  if (stats.stddev.has_value()) {
    proto_stats->set_stddev(*stats.stddev);
  }
  if (stats.min.has_value()) {
    proto_stats->set_min(*stats.min);
  }
  if (stats.max.has_value()) {
    proto_stats->set_max(*stats.max);
  }
}

bool WriteMetricsToFile(const std::string& path,
                        const webrtc::test_metrics::MetricsSet& metrics_set) {
  std::string data;
  bool ok = metrics_set.SerializeToString(&data);
  if (!ok) {
    RTC_LOG(LS_ERROR) << "Failed to serialize histogram set to string";
    return false;
  }

  CreateDir(DirName(path));
  FILE* output = fopen(path.c_str(), "wb");
  if (output == NULL) {
    RTC_LOG(LS_ERROR) << "Failed to write to " << path;
    return false;
  }
  size_t written = fwrite(data.c_str(), sizeof(char), data.size(), output);
  fclose(output);

  if (written != data.size()) {
    size_t expected = data.size();
    RTC_LOG(LS_ERROR) << "Wrote " << written << ", tried to write " << expected;
    return false;
  }
  return true;
}
#endif  // WEBRTC_ENABLE_PROTOBUF

}  // namespace

MetricsSetProtoFileExporter::Options::Options(
    absl::string_view export_file_path)
    : export_file_path(export_file_path) {}
MetricsSetProtoFileExporter::Options::Options(
    absl::string_view export_file_path,
    bool export_whole_time_series)
    : export_file_path(export_file_path),
      export_whole_time_series(export_whole_time_series) {}

bool MetricsSetProtoFileExporter::Export(rtc::ArrayView<const Metric> metrics) {
#if WEBRTC_ENABLE_PROTOBUF
  webrtc::test_metrics::MetricsSet metrics_set;
  for (const Metric& metric : metrics) {
    webrtc::test_metrics::Metric* metric_proto = metrics_set.add_metrics();
    metric_proto->set_name(metric.name);
    metric_proto->set_unit(ToProtoUnit(metric.unit));
    metric_proto->set_improvement_direction(
        ToProtoImprovementDirection(metric.improvement_direction));
    metric_proto->set_test_case(metric.test_case);
    for (const auto& [key, value] : metric.metric_metadata) {
      metric_proto->mutable_metric_metadata()->insert({key, value});
    }

    if (options_.export_whole_time_series) {
      SetTimeSeries(metric.time_series, metric_proto->mutable_time_series());
    }
    SetStats(metric.stats, metric_proto->mutable_stats());
  }

  return WriteMetricsToFile(options_.export_file_path, metrics_set);
#else
  RTC_LOG(LS_ERROR)
      << "Compile with protobuf support to properly use this class";
  return false;
#endif
}

}  // namespace test
}  // namespace webrtc
