// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "garnet/lib/measure/results.h"

#include "garnet/public/lib/fxl/logging.h"

#include <sstream>

namespace tracing {
namespace measure {

namespace {

std::string GetLabel(const measure::DurationSpec& spec) {
  std::ostringstream os;
  os << spec.event.name.c_str() << " (" << spec.event.category.c_str() << ")";
  return os.str();
}

std::string GetLabel(const measure::ArgumentValueSpec& spec) {
  std::ostringstream os;
  os << spec.event.name.c_str() << " (" << spec.event.category.c_str() << "), ";
  os << spec.argument_name.c_str();
  return os.str();
}

std::string GetLabel(const measure::TimeBetweenSpec& spec) {
  std::ostringstream os;
  os << spec.first_event.name.c_str() << " ("
     << spec.first_event.category.c_str() << ") to ";
  os << spec.second_event.name.c_str() << " ("
     << spec.second_event.category.c_str() << ")";
  return os.str();
}

std::string GetUnit(const measure::ArgumentValueSpec& spec) {
  return spec.argument_unit;
}

std::string GetUnit(const measure::DurationSpec& spec) { return "ms"; }

std::string GetUnit(const measure::TimeBetweenSpec& spec) { return "ms"; }

template <typename Spec, typename T>
Result ComputeSingle(Spec spec, const std::vector<T>& recorded_values) {
  Result result;
  if (spec.common.output_test_name.empty()) {
    result.label = GetLabel(spec);
  } else {
    result.label = spec.common.output_test_name;
  }
  result.unit = GetUnit(spec);
  result.split_first = spec.common.split_first;

  if ((spec.common.expected_sample_count > 0) &&
      (spec.common.expected_sample_count != recorded_values.size())) {
    FXL_LOG(ERROR) << "Number of recorded samples for an event " << result.label
                   << " does not match the expected number (expected "
                   << spec.common.expected_sample_count << ", got "
                   << recorded_values.size() << ").";
    return result;
  }

  std::copy(recorded_values.begin(), recorded_values.end(),
            std::back_inserter(result.values));
  return result;
}

template <typename T>
const T& get_or_default(const std::unordered_map<uint64_t, T>& dictionary,
                        uint64_t id, const T& default_value) {
  return dictionary.count(id) ? dictionary.at(id) : default_value;
}

std::vector<double> ticks_to_ms(const std::vector<uint64_t> ticks,
                                uint64_t ticks_per_second) {
  std::vector<double> milliseconds(ticks.size());
  double ms_per_tick = 1'000.0 / ticks_per_second;
  std::transform(ticks.begin(), ticks.end(), milliseconds.begin(),
                 [&ms_per_tick](uint64_t tick) { return tick * ms_per_tick; });
  return milliseconds;
}

}  // namespace

std::vector<Result> ComputeResults(
    const Measurements& measurements,
    const std::unordered_map<uint64_t, std::vector<uint64_t>>& recorded_values,
    uint64_t ticks_per_second) {
  std::vector<Result> results;
  const std::vector<uint64_t> no_recorded_values;
  std::string empty_string;

  for (auto& measure_spec : measurements.duration) {
    auto duration_values =
        ticks_to_ms(get_or_default(recorded_values, measure_spec.common.id,
                                   no_recorded_values),
                    ticks_per_second);
    results.push_back(ComputeSingle(measure_spec, duration_values));
  }
  for (auto& measure_spec : measurements.argument_value) {
    auto argument_values = get_or_default(
        recorded_values, measure_spec.common.id, no_recorded_values);
    results.push_back(ComputeSingle(measure_spec, argument_values));
  }
  for (auto& measure_spec : measurements.time_between) {
    auto time_between_values =
        ticks_to_ms(get_or_default(recorded_values, measure_spec.common.id,
                                   no_recorded_values),
                    ticks_per_second);
    results.push_back(ComputeSingle(measure_spec, time_between_values));
  }

  return results;
}

}  // namespace measure
}  // namespace tracing
