// Copyright 2018 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 "src/logger/fake_logger.h"

#include <map>
#include <memory>
#include <set>
#include <string>
#include <tuple>
#include <utility>
#include <vector>

#include "src/logger/logger_interface.h"
#include "src/public/lib/status.h"
#include "src/registry/project_configs.h"

namespace cobalt::logger::testing {

namespace {

template <class EventType>
void CopyEventCodesAndComponent(const std::vector<uint32_t>& event_codes,
                                const std::string& component, EventType* event) {
  for (auto event_code : event_codes) {
    event->add_event_code(event_code);
  }
  event->set_component(component);
}

template <class EventType>
void CopyEventCodes(const std::vector<uint32_t>& event_codes, EventType* event) {
  for (auto event_code : event_codes) {
    event->add_event_code(event_code);
  }
}

}  // namespace

// TODO(fxbug.dev/85571): NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
Status FakeLogger::LogEvent(uint32_t metric_id, uint32_t event_code) {
  call_count_ += 1;

  Event event;
  event.set_metric_id(metric_id);
  event.mutable_event_occurred_event()->set_event_code(event_code);
  TrackEvent(event);

  return Status::OkStatus();
}

Status FakeLogger::LogEventCount(
    uint32_t metric_id, const std::vector<uint32_t>& event_codes, const std::string& component,
    // TODO(fxbug.dev/85571): NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
    int64_t period_duration_micros, uint32_t count) {
  call_count_ += 1;

  Event event;
  event.set_metric_id(metric_id);
  auto* event_count_event = event.mutable_event_count_event();
  CopyEventCodesAndComponent(event_codes, component, event_count_event);
  event_count_event->set_period_duration_micros(period_duration_micros);
  event_count_event->set_count(count);
  TrackEvent(event);

  return Status::OkStatus();
}

Status FakeLogger::LogElapsedTime(uint32_t metric_id, const std::vector<uint32_t>& event_codes,
                                  const std::string& component, int64_t elapsed_micros) {
  call_count_ += 1;

  Event event;
  event.set_metric_id(metric_id);
  auto* elapsed_time_event = event.mutable_elapsed_time_event();
  CopyEventCodesAndComponent(event_codes, component, elapsed_time_event);
  elapsed_time_event->set_elapsed_micros(elapsed_micros);
  TrackEvent(event);

  return Status::OkStatus();
}

Status FakeLogger::LogFrameRate(uint32_t metric_id, const std::vector<uint32_t>& event_codes,
                                const std::string& component, float fps) {
  call_count_ += 1;

  Event event;
  event.set_metric_id(metric_id);
  auto* frame_rate_event = event.mutable_frame_rate_event();
  CopyEventCodesAndComponent(event_codes, component, frame_rate_event);
  // NOLINTNEXTLINE readability-magic-numbers
  frame_rate_event->set_frames_per_1000_seconds(std::round(fps * 1000.0));
  TrackEvent(event);

  return Status::OkStatus();
}

Status FakeLogger::LogMemoryUsage(uint32_t metric_id, const std::vector<uint32_t>& event_codes,
                                  const std::string& component, int64_t bytes) {
  call_count_ += 1;

  Event event;
  event.set_metric_id(metric_id);
  auto* memory_usage_event = event.mutable_memory_usage_event();
  CopyEventCodesAndComponent(event_codes, component, memory_usage_event);
  memory_usage_event->set_bytes(bytes);
  TrackEvent(event);

  return Status::OkStatus();
}

Status FakeLogger::LogIntHistogram(uint32_t metric_id, const std::vector<uint32_t>& event_codes,
                                   const std::string& component, HistogramPtr histogram) {
  call_count_ += 1;

  Event event;
  event.set_metric_id(metric_id);
  auto* int_histogram_event = event.mutable_int_histogram_event();
  CopyEventCodesAndComponent(event_codes, component, int_histogram_event);
  int_histogram_event->mutable_buckets()->Swap(histogram.get());
  TrackEvent(event);

  return Status::OkStatus();
}

// TODO(fxbug.dev/85571): NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
Status FakeLogger::LogOccurrence(uint32_t metric_id, uint64_t count,
                                 const std::vector<uint32_t>& event_codes) {
  call_count_ += 1;

  Event event;
  event.set_metric_id(metric_id);
  auto* occurrence_event = event.mutable_occurrence_event();
  CopyEventCodes(event_codes, occurrence_event);
  occurrence_event->set_count(count);
  TrackEvent(event);

  return Status::OkStatus();
}

// TODO(fxbug.dev/85571): NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
Status FakeLogger::LogInteger(uint32_t metric_id, int64_t value,
                              const std::vector<uint32_t>& event_codes) {
  call_count_ += 1;

  Event event;
  event.set_metric_id(metric_id);
  auto* integer_event = event.mutable_integer_event();
  CopyEventCodes(event_codes, integer_event);
  integer_event->set_value(value);
  TrackEvent(event);

  return Status::OkStatus();
}

Status FakeLogger::LogIntegerHistogram(uint32_t metric_id, HistogramPtr histogram,
                                       const std::vector<uint32_t>& event_codes) {
  call_count_ += 1;

  Event event;
  event.set_metric_id(metric_id);
  auto* integer_histogram_event = event.mutable_integer_histogram_event();
  CopyEventCodes(event_codes, integer_histogram_event);
  integer_histogram_event->mutable_buckets()->Swap(histogram.get());
  TrackEvent(event);

  return Status::OkStatus();
}

Status FakeLogger::LogString(uint32_t metric_id, const std::string& string_value,
                             const std::vector<uint32_t>& event_codes) {
  call_count_ += 1;

  Event event;
  event.set_metric_id(metric_id);
  auto* string_event = event.mutable_string_event();
  CopyEventCodes(event_codes, string_event);
  string_event->set_string_value(string_value);
  TrackEvent(event);

  return Status::OkStatus();
}

Status FakeLogger::LogCustomEvent(uint32_t metric_id, EventValuesPtr event_values) {
  call_count_ += 1;

  Event event;
  event.set_metric_id(metric_id);
  event.mutable_custom_event()->mutable_values()->swap(*event_values);
  TrackEvent(event);

  return Status::OkStatus();
}

Status FakeLogger::LogSerializedCustomEvent(uint32_t metric_id,
                                            std::unique_ptr<std::string> serialized_proto) {
  call_count_ += 1;

  Event event;
  event.set_metric_id(metric_id);
  event.mutable_custom_event()->mutable_serialized_proto()->swap(*serialized_proto);
  last_event_logged_ = event;

  return Status::OkStatus();
}

}  // namespace cobalt::logger::testing
