// 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/event_loggers.h"

#include <memory>
#include <string>

#include <google/protobuf/repeated_field.h>

#include "src/algorithms/rappor/rappor_config_helper.h"
#include "src/lib/util/datetime_util.h"
#include "src/lib/util/status.h"
#include "src/logger/event_record.h"
#include "src/logging.h"
#include "src/pb/event.pb.h"
#include "src/pb/observation.pb.h"
#include "src/registry/metric_definition.pb.h"
#include "src/registry/report_definition.pb.h"
#include "src/tracing.h"

namespace cobalt::logger::internal {

using ::cobalt::local_aggregation::EventAggregator;
using ::cobalt::rappor::RapporConfigHelper;
using ::cobalt::util::TimeToDayIndex;
using ::cobalt::util::TimeToHourId;
using ::google::protobuf::RepeatedField;
using ::google::protobuf::RepeatedPtrField;

constexpr char TRACE_PREFIX[] = "[COBALT_EVENT_TRACE] ";

namespace {

Status FromStatus(const cobalt::util::Status& status) {
  switch (status.error_code()) {
    case cobalt::util::StatusCode::OK:
      return kOK;
    case cobalt::util::StatusCode::INVALID_ARGUMENT:
      return kInvalidArguments;
    default:
      return kOther;
  }
}

}  // namespace

std::unique_ptr<EventLogger> EventLogger::Create(
    MetricDefinition::MetricType metric_type, const Encoder* encoder,
    EventAggregator* event_aggregator, local_aggregation::LocalAggregation* local_aggregation,
    const ObservationWriter* observation_writer,
    const system_data::SystemDataInterface* system_data) {
  switch (metric_type) {
    case MetricDefinition::EVENT_OCCURRED: {
      return std::make_unique<internal::EventOccurredEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::EVENT_COUNT: {
      return std::make_unique<internal::EventCountEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::ELAPSED_TIME: {
      return std::make_unique<internal::ElapsedTimeEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::FRAME_RATE: {
      return std::make_unique<internal::FrameRateEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::MEMORY_USAGE: {
      return std::make_unique<internal::MemoryUsageEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::INT_HISTOGRAM: {
      return std::make_unique<internal::IntHistogramEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::OCCURRENCE: {
      return std::make_unique<internal::OccurrenceEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::INTEGER: {
      return std::make_unique<internal::IntegerEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::INTEGER_HISTOGRAM: {
      return std::make_unique<internal::IntegerHistogramEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::STRING: {
      return std::make_unique<internal::StringEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    case MetricDefinition::CUSTOM: {
      return std::make_unique<internal::CustomEventLogger>(
          encoder, event_aggregator, local_aggregation, observation_writer, system_data);
    }
    default: {
      LOG(ERROR) << "Failed to process a metric type of " << metric_type;
      return nullptr;
    }
  }
}

std::string EventLogger::TraceEvent(const EventRecord& event_record) {
  if (!event_record.metric()->meta_data().also_log_locally()) {
    return "";
  }

  auto event = event_record.event();

  std::stringstream ss;
  ss << "Day index: " << event->day_index() << std::endl;
  if (event->has_event_occurred_event()) {
    const auto& e = event->event_occurred_event();
    ss << "EventOccurredEvent: " << e.event_code() << std::endl;
  } else if (event->has_event_count_event()) {
    const auto& e = event->event_count_event();
    ss << "EventCountEvent:" << std::endl;
    ss << "EventCodes:";
    for (const auto& code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", Component: " << e.component()
       << ", PeriodDurationMicros: " << e.period_duration_micros() << ", Count: " << e.count()
       << std::endl;
  } else if (event->has_elapsed_time_event()) {
    const auto& e = event->elapsed_time_event();
    ss << "ElapsedTimeEvent:" << std::endl;
    ss << "EventCodes:";
    for (const auto& code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", Component: " << e.component() << ", ElapsedMicros: " << e.elapsed_micros()
       << std::endl;
  } else if (event->has_frame_rate_event()) {
    const auto& e = event->frame_rate_event();
    ss << "FrameRateEvent:" << std::endl;
    ss << "EventCodes:";
    for (const auto& code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", Component: " << e.component()
       << ", FramesPer1000Seconds: " << e.frames_per_1000_seconds() << std::endl;
  } else if (event->has_memory_usage_event()) {
    const auto& e = event->memory_usage_event();
    ss << "MemoryUsageEvent:" << std::endl;
    ss << "EventCodes:";
    for (const auto& code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", Component: " << e.component() << ", Bytes: " << e.bytes() << std::endl;
  } else if (event->has_int_histogram_event()) {
    const auto& e = event->int_histogram_event();
    ss << "IntHistogramEvent:" << std::endl;
    ss << "EventCodes:";
    for (const auto& code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", Component: " << e.component() << std::endl;
    for (const auto& bucket : e.buckets()) {
      ss << "| " << bucket.index() << " = " << bucket.count() << std::endl;
    }
  } else if (event->has_occurrence_event()) {
    const OccurrenceEvent& e = event->occurrence_event();
    ss << "OccurrenceEvent:" << std::endl;
    ss << "EventCodes:";
    for (uint32_t code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", Count: " << e.count() << std::endl;
  } else if (event->has_integer_event()) {
    const IntegerEvent& e = event->integer_event();
    ss << "IntegerEvent:" << std::endl;
    ss << "EventCodes:";
    for (uint32_t code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", Value: " << e.value() << std::endl;
  } else if (event->has_integer_histogram_event()) {
    const IntegerHistogramEvent& e = event->integer_histogram_event();
    ss << "IntegerHistogramEvent:" << std::endl;
    ss << "EventCodes:";
    for (uint32_t code : e.event_code()) {
      ss << " " << code;
    }
    for (const HistogramBucket& bucket : e.buckets()) {
      ss << "| " << bucket.index() << " = " << bucket.count() << std::endl;
    }
  } else if (event->has_string_event()) {
    const StringEvent& e = event->string_event();
    ss << "StringEvent:" << std::endl;
    ss << "EventCodes:";
    for (uint32_t code : e.event_code()) {
      ss << " " << code;
    }
    ss << ", String: " << e.string_value() << std::endl;
  } else if (event->has_custom_event()) {
    const auto& e = event->custom_event();
    ss << "CustomEvent:";
    if (e.values().empty()) {
      ss << " (Empty)";
    }
    ss << std::endl;
    for (const auto& entry : e.values()) {
      switch (entry.second.data_case()) {
        ss << "| " << entry.first << " = ";
        case CustomDimensionValue::kStringValue:
          ss << entry.second.string_value();
          break;
        case CustomDimensionValue::kIntValue:
          ss << entry.second.int_value();
          break;
        case CustomDimensionValue::kBlobValue:
          ss << "Blob";
          break;
        case CustomDimensionValue::kIndexValue:
          ss << entry.second.index_value();
          break;
        case CustomDimensionValue::kDoubleValue:
          ss << entry.second.double_value();
          break;
        default:
          ss << "No dimension value";
          break;
      }
      ss << std::endl;
    }
  }

  return ss.str();
}

void EventLogger::TraceLogFailure(const Status& status, const EventRecord& event_record,
                                  const std::string& trace, const ReportDefinition& report) {
  if (!event_record.metric()->meta_data().also_log_locally()) {
    return;
  }

  LOG(INFO) << TRACE_PREFIX << "("
            << event_record.project_context()->RefMetric(event_record.metric()).FullyQualifiedName()
            << "): Error (" << status << ")" << std::endl
            << trace << "While trying to send report: " << report.report_name() << std::endl;
}

void EventLogger::TraceLogSuccess(const EventRecord& event_record, const std::string& trace) {
  if (!event_record.metric()->meta_data().also_log_locally()) {
    return;
  }

  LOG(INFO) << TRACE_PREFIX << "("
            << event_record.project_context()->RefMetric(event_record.metric()).FullyQualifiedName()
            << "):" << std::endl
            << trace;
}

Status EventLogger::Log(std::unique_ptr<EventRecord> event_record,
                        const std::chrono::system_clock::time_point& event_timestamp) {
  TRACE_DURATION("cobalt_core", "EventLogger::Log", "metric_id", event_record->metric()->id());

  FinalizeEvent(event_record.get(), event_timestamp);

  if (system_data_) {
    if (system_data_->release_stage() > event_record->metric()->meta_data().max_release_stage()) {
      // Quietly ignore this metric.
      LOG_FIRST_N(INFO, 10) << "Not logging metric `"
                            << event_record->project_context()->FullMetricName(
                                   *event_record->metric())
                            << "` because its max_release_stage ("
                            << event_record->metric()->meta_data().max_release_stage()
                            << ") is lower than the device's current release_stage: "
                            << system_data_->release_stage();
      return kOK;
    }
  }

  int num_reports = event_record->metric()->reports_size();
  int report_index = 0;
  if (event_record->metric()->reports_size() == 0) {
    VLOG(1) << "Warning: An event was logged for a metric with no reports "
               "defined: "
            << event_record->project_context()->FullMetricName(*event_record->metric());
  }

  // Store the trace before attempting to log the event. This way, if parts of
  // the event are moved out of the object, the resulting trace will still have
  // useful information.
  auto trace = TraceEvent(*event_record);

  for (const auto& report : event_record->metric()->reports()) {
    auto status = MaybeUpdateLocalAggregation(report, *event_record);
    if (status != kOK) {
      TraceLogFailure(status, *event_record, trace, report);
      return status;
    }

    // If we are processing the final report, then we set may_invalidate
    // to true in order to allow data to be moved out of |event_record|
    // instead of being copied. One example where this is useful is when
    // creating an immediate Observation of type Histogram. In that case
    // we can move the histogram from the Event to the Observation and
    // avoid copying. Since the |event_record| is invalidated, any other
    // operation on the |event_record| must be performed before this for
    // loop.
    bool may_invalidate = ++report_index == num_reports;
    status = MaybeGenerateImmediateObservation(report, may_invalidate, event_record.get());
    if (status != kOK) {
      TraceLogFailure(status, *event_record, trace, report);
      return status;
    }
  }

  TraceLogSuccess(*event_record, trace);
  return kOK;
}

Status EventLogger::PrepareAndValidateEvent(uint32_t metric_id,
                                            MetricDefinition::MetricType expected_type,
                                            EventRecord* event_record) {
  if (event_record->metric() == nullptr) {
    LOG(ERROR) << "There is no metric with ID '" << metric_id << "' registered "
               << "in project '" << event_record->project_context()->FullyQualifiedName() << "'.";
    return kInvalidArguments;
  }
  if (event_record->metric()->metric_type() != expected_type) {
    LOG(ERROR) << "Metric "
               << event_record->project_context()->FullMetricName(*event_record->metric())
               << " is not of type " << expected_type << " instead it is of type "
               << event_record->metric()->metric_type() << ".";
    return kInvalidArguments;
  }
  return ValidateEvent(*event_record);
}

void EventLogger::FinalizeEvent(EventRecord* event_record,
                                const std::chrono::system_clock::time_point& event_timestamp) {
  // Compute the day_index and hour index.
  auto now = std::chrono::system_clock::to_time_t(event_timestamp);
  event_record->event()->set_day_index(
      TimeToDayIndex(now, event_record->metric()->time_zone_policy()));
  event_record->event()->set_hour_id(TimeToHourId(now, event_record->metric()->time_zone_policy()));
}

Status EventLogger::ValidateEvent(const EventRecord& /*event_record*/) { return kOK; }

Status EventLogger::ValidateEventCodes(const MetricDefinition& metric,
                                       const RepeatedField<uint32_t>& event_codes,
                                       const std::string& full_metric_name) {
  // Special case: Users of the version of the Log*() method that takes
  // a single event code as opposed to a vector of event codes use the
  // convention of passing a zero value for the single event code in the
  // case that the metric does not have any metric dimensions defined. We have
  // no way of distinguishing here that case from the case in which the user
  // invoked the other version of the method and explicitly passed a vector of
  // length one containing a single zero event code. Therefore we must accept
  // a single 0 event code when there are no metric dimensions defined.
  // The packing of multiple event codes into a single integer field in an
  // Observation (see config/packed_event_codes.h) does not distinguish
  // between a single event code with value 0 and an empty list of event codes.
  // Therefore the server also cannot tell the difference between these two
  // cases just by looking at an Observation and relies on the metric definition
  // to distinguish them. Consequently there is no harm in us passing the
  // single zero value to the Encoder: It will produce the same Observation
  // whether or not we do.
  if (metric.metric_dimensions_size() == 0 && event_codes.size() == 1 && event_codes.Get(0) == 0) {
    return kOK;
  }
  // When new dimensions are added to a metric, they can only be appended, not deleted or inserted.
  // Because of this, and because metric definitions may change before the matching code does, we
  // want to accept events where fewer than the expected number of event_codes have been provided.
  if (event_codes.size() > metric.metric_dimensions_size()) {
    LOG(ERROR) << "The number of event_codes given, " << event_codes.size()
               << ", is more than the number of metric_dimensions, "
               << metric.metric_dimensions_size() << ", for metric " << full_metric_name << ".";
    return kInvalidArguments;
  }
  for (int i = 0; i < event_codes.size(); i++) {
    const auto& dim = metric.metric_dimensions(i);
    auto code = event_codes.Get(i);

    // This verifies the two possible validation modes for a metric_dimension.
    //
    // 1. If it has a max_event_code, then all we do is verify that the supplied
    //    code is <= that value
    //
    // 2. If no max_event_code is specified, we verify that the supplied code
    //    maps to one of the values in the event_code map.
    if (dim.max_event_code() > 0) {
      if (code > dim.max_event_code()) {
        LOG(ERROR) << "The event_code given for dimension " << i << ", " << code
                   << ", exceeds the max_event_code for that dimension, " << dim.max_event_code()
                   << ", for metric " << full_metric_name;
        return kInvalidArguments;
      }
    } else {
      bool valid = false;
      for (const auto& event_code : dim.event_codes()) {
        if (event_code.first == code) {
          valid = true;
          break;
        }
      }

      if (!valid) {
        LOG(ERROR) << "The event_code given for dimension " << i << ", " << code
                   << ", is not a valid event code for that dimension."
                   << ". You must either define this event code in"
                      " the metric_dimension, or set max_event_code >= "
                   << code << ", for metric " << full_metric_name;
        return kInvalidArguments;
      }
    }
  }
  return kOK;
}

// The default implementation of MaybeUpdateLocalAggregation does nothing
// and returns OK.
Status EventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& /*report*/,
                                                const EventRecord& /*event_record*/) {
  return kOK;
}

Status EventLogger::MaybeGenerateImmediateObservation(const ReportDefinition& report,
                                                      bool may_invalidate,
                                                      EventRecord* event_record) {
  TRACE_DURATION("cobalt_core", "EventLogger::MaybeGenerateImmediateObservation");

  auto encoder_result = MaybeEncodeImmediateObservation(report, may_invalidate, event_record);
  if (encoder_result.status != kOK) {
    return encoder_result.status;
  }
  if (encoder_result.observation == nullptr) {
    return kOK;
  }
  return observation_writer_->WriteObservation(encoder_result.observation,
                                               std::move(encoder_result.metadata));
}

// The default implementation of MaybeEncodeImmediateObservation does
// nothing and returns OK.
Encoder::Result EventLogger::MaybeEncodeImmediateObservation(const ReportDefinition& /*report*/,
                                                             bool /*may_invalidate*/,
                                                             EventRecord* /*event_record*/) {
  TRACE_DURATION("cobalt_core", "EventLogger::MaybeEncodeImmediateObservation");
  Encoder::Result result;
  result.status = kOK;
  result.observation = nullptr;
  return result;
}

Encoder::Result EventLogger::BadReportType(const std::string& full_metric_name,
                                           const ReportDefinition& report) {
  LOG(ERROR) << "Invalid Cobalt config: Report " << report.report_name() << " for metric "
             << full_metric_name << " is not of an appropriate type for the metric type.";
  Encoder::Result encoder_result;
  encoder_result.status = kInvalidConfig;
  return encoder_result;
}

/////////////// EventOccurredEventLogger method implementations ///////////////////

Status EventOccurredEventLogger::ValidateEvent(const EventRecord& event_record) {
  CHECK(event_record.event()->has_event_occurred_event());
  if (event_record.metric()->metric_dimensions_size() != 1) {
    LOG(ERROR) << "The Metric "
               << event_record.project_context()->FullMetricName(*event_record.metric())
               << " has the wrong number of metric_dimensions. A metric of "
                  "type EVENT_OCCURRED must have exactly one metric_dimension.";
    return kInvalidConfig;
  }

  const auto& event_occurred_event = event_record.event()->event_occurred_event();
  if (event_occurred_event.event_code() >
      event_record.metric()->metric_dimensions(0).max_event_code()) {
    LOG(ERROR) << "The event_code " << event_occurred_event.event_code() << " exceeds "
               << event_record.metric()->metric_dimensions(0).max_event_code()
               << ", the max_event_code for Metric "
               << event_record.project_context()->FullMetricName(*event_record.metric()) << ".";
    return kInvalidArguments;
  }
  return kOK;
}

Encoder::Result EventOccurredEventLogger::MaybeEncodeImmediateObservation(
    const ReportDefinition& report, bool /*may_invalidate*/, EventRecord* event_record) {
  TRACE_DURATION("cobalt_core", "EventOccurredEventLogger::MaybeEncodeImmediateObservation");
  const MetricDefinition& metric = *(event_record->metric());
  const Event& event = *(event_record->event());
  CHECK(event.has_event_occurred_event());
  const auto& event_occurred_event = event.event_occurred_event();
  switch (report.report_type()) {
    // Each report type has its own logic for generating immediate
    // observations.
    case ReportDefinition::SIMPLE_OCCURRENCE_COUNT: {
      return encoder()->EncodeBasicRapporObservation(
          event_record->project_context()->RefMetric(&metric), &report, event.day_index(),
          event_occurred_event.event_code(), RapporConfigHelper::BasicRapporNumCategories(metric));
    }
      // Report type UNIQUE_N_DAY_ACTIVES is valid but should not result in
      // generation of an immediate observation.
    case ReportDefinition::UNIQUE_N_DAY_ACTIVES: {
      Encoder::Result result;
      result.status = kOK;
      result.observation = nullptr;
      result.metadata = nullptr;
      return result;
    }

    default:
      return BadReportType(event_record->project_context()->FullMetricName(metric), report);
  }
}

Status EventOccurredEventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                             const EventRecord& event_record) {
  switch (report.report_type()) {
    case ReportDefinition::UNIQUE_N_DAY_ACTIVES: {
      return event_aggregator()->AddUniqueActivesEvent(report.id(), event_record);
    }
    default:
      return kOK;
  }
}

///////////// EventCountEventLogger method implementations //////////////////////////

Status EventCountEventLogger::ValidateEvent(const EventRecord& event_record) {
  CHECK(event_record.metric());
  const auto& metric = *(event_record.metric());
  return ValidateEventCodes(metric, event_record.event()->event_count_event().event_code(),
                            event_record.project_context()->FullMetricName(metric));
}

Encoder::Result EventCountEventLogger::MaybeEncodeImmediateObservation(
    const ReportDefinition& report, bool /*may_invalidate*/, EventRecord* event_record) {
  TRACE_DURATION("cobalt_core", "EventCountEventLogger::MaybeEncodeImmediateObservation");
  const MetricDefinition& metric = *(event_record->metric());
  const Event& event = *(event_record->event());
  CHECK(event.has_event_count_event());
  auto* event_count_event = event_record->event()->mutable_event_count_event();
  switch (report.report_type()) {
    // Each report type has its own logic for generating immediate observations.
    case ReportDefinition::EVENT_COMPONENT_OCCURRENCE_COUNT:
    case ReportDefinition::INT_RANGE_HISTOGRAM:
    case ReportDefinition::NUMERIC_AGGREGATION: {
      return encoder()->EncodeIntegerEventObservation(
          event_record->project_context()->RefMetric(&metric), &report, event.day_index(),
          event_count_event->event_code(), event_count_event->component(),
          event_count_event->count());
    }
    // Report type PER_DEVICE_NUMERIC_STATS and PER_DEVICE_HISTOGRAM are valid but should not result
    // in generation of an immediate observation.
    case ReportDefinition::PER_DEVICE_NUMERIC_STATS:
    case ReportDefinition::PER_DEVICE_HISTOGRAM: {
      Encoder::Result result;
      result.status = kOK;
      result.observation = nullptr;
      result.metadata = nullptr;
      return result;
    }

    default:
      return BadReportType(event_record->project_context()->FullMetricName(metric), report);
  }
}

Status EventCountEventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                          const EventRecord& event_record) {
  switch (report.report_type()) {
    case ReportDefinition::PER_DEVICE_NUMERIC_STATS:
    case ReportDefinition::PER_DEVICE_HISTOGRAM: {
      return event_aggregator()->AddEventCountEvent(report.id(), event_record);
    }
    default:
      return kOK;
  }
}

///////////// IntegerPerformanceEventLogger method implementations /////////////

Encoder::Result IntegerPerformanceEventLogger::MaybeEncodeImmediateObservation(
    const ReportDefinition& report, bool /*may_invalidate*/, EventRecord* event_record) {
  TRACE_DURATION("cobalt_core", "IntegerPerformanceEventLogger::MaybeEncodeImmediateObservation");
  const MetricDefinition& metric = *(event_record->metric());
  const Event& event = *(event_record->event());
  switch (report.report_type()) {
    // Each report type has its own logic for generating immediate
    // observations.
    case ReportDefinition::NUMERIC_AGGREGATION:
    case ReportDefinition::INT_RANGE_HISTOGRAM: {
      return encoder()->EncodeIntegerEventObservation(
          event_record->project_context()->RefMetric(&metric), &report, event.day_index(),
          EventCodes(event), Component(event), IntValue(event));
      break;
    }
    // Report type PER_DEVICE_NUMERIC_STATS and PER_DEVICE_HISTOGRAM are valid but should not result
    // in generation of an immediate observation.
    case ReportDefinition::PER_DEVICE_NUMERIC_STATS:
    case ReportDefinition::PER_DEVICE_HISTOGRAM: {
      Encoder::Result result;
      result.status = kOK;
      result.observation = nullptr;
      result.metadata = nullptr;
      return result;
    }
    default:
      return BadReportType(event_record->project_context()->FullMetricName(metric), report);
  }
}

////////////// ElapsedTimeEventLogger method implementations ///////////////////

const RepeatedField<uint32_t>& ElapsedTimeEventLogger::EventCodes(const Event& event) {
  CHECK(event.has_elapsed_time_event());
  return event.elapsed_time_event().event_code();
}

std::string ElapsedTimeEventLogger::Component(const Event& event) {
  CHECK(event.has_elapsed_time_event());
  return event.elapsed_time_event().component();
}

int64_t ElapsedTimeEventLogger::IntValue(const Event& event) {
  CHECK(event.has_elapsed_time_event());
  return event.elapsed_time_event().elapsed_micros();
}

Status ElapsedTimeEventLogger::ValidateEvent(const EventRecord& event_record) {
  CHECK(event_record.metric());
  const auto& metric = *(event_record.metric());
  return ValidateEventCodes(metric, event_record.event()->elapsed_time_event().event_code(),
                            event_record.project_context()->FullMetricName(metric));
}

Status ElapsedTimeEventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                           const EventRecord& event_record) {
  switch (report.report_type()) {
    case ReportDefinition::PER_DEVICE_NUMERIC_STATS:
    case ReportDefinition::PER_DEVICE_HISTOGRAM: {
      return event_aggregator()->AddElapsedTimeEvent(report.id(), event_record);
    }
    default:
      return kOK;
  }
}

//////////////// FrameRateEventLogger method implementations ///////////////////

const RepeatedField<uint32_t>& FrameRateEventLogger::EventCodes(const Event& event) {
  CHECK(event.has_frame_rate_event());
  return event.frame_rate_event().event_code();
}

std::string FrameRateEventLogger::Component(const Event& event) {
  CHECK(event.has_frame_rate_event());
  return event.frame_rate_event().component();
}

int64_t FrameRateEventLogger::IntValue(const Event& event) {
  CHECK(event.has_frame_rate_event());
  return event.frame_rate_event().frames_per_1000_seconds();
}

Status FrameRateEventLogger::ValidateEvent(const EventRecord& event_record) {
  CHECK(event_record.metric());
  const auto& metric = *(event_record.metric());
  return ValidateEventCodes(metric, event_record.event()->frame_rate_event().event_code(),
                            event_record.project_context()->FullMetricName(metric));
}

Status FrameRateEventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                         const EventRecord& event_record) {
  switch (report.report_type()) {
    case ReportDefinition::PER_DEVICE_NUMERIC_STATS:
    case ReportDefinition::PER_DEVICE_HISTOGRAM: {
      return event_aggregator()->AddFrameRateEvent(report.id(), event_record);
    }
    default:
      return kOK;
  }
}

////////////// MemoryUsageEventLogger method implementations ///////////////////
const RepeatedField<uint32_t>& MemoryUsageEventLogger::EventCodes(const Event& event) {
  CHECK(event.has_memory_usage_event());
  return event.memory_usage_event().event_code();
}

std::string MemoryUsageEventLogger::Component(const Event& event) {
  CHECK(event.has_memory_usage_event());
  return event.memory_usage_event().component();
}

int64_t MemoryUsageEventLogger::IntValue(const Event& event) {
  CHECK(event.has_memory_usage_event());
  return event.memory_usage_event().bytes();
}

Status MemoryUsageEventLogger::ValidateEvent(const EventRecord& event_record) {
  CHECK(event_record.metric());
  const auto& metric = *(event_record.metric());
  return ValidateEventCodes(metric, event_record.event()->memory_usage_event().event_code(),
                            event_record.project_context()->FullMetricName(metric));
}

Status MemoryUsageEventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                           const EventRecord& event_record) {
  switch (report.report_type()) {
    case ReportDefinition::PER_DEVICE_NUMERIC_STATS:
    case ReportDefinition::PER_DEVICE_HISTOGRAM: {
      return event_aggregator()->AddMemoryUsageEvent(report.id(), event_record);
    }
    default:
      return kOK;
  }
}

///////////// IntHistogramEventLogger method implementations ///////////////////

Status IntHistogramEventLogger::ValidateEvent(const EventRecord& event_record) {
  CHECK(event_record.event()->has_int_histogram_event());
  const auto& int_histogram_event = event_record.event()->int_histogram_event();
  CHECK(event_record.metric());
  const auto& metric = *(event_record.metric());

  auto status = ValidateEventCodes(metric, int_histogram_event.event_code(),
                                   event_record.project_context()->FullMetricName(metric));
  if (status != kOK) {
    return status;
  }

  if (!metric.has_int_buckets()) {
    LOG(ERROR) << "Invalid Cobalt config: Metric "
               << event_record.project_context()->FullMetricName(metric)
               << " does not have an |int_buckets| field set.";
    return kInvalidConfig;
  }
  const auto& int_buckets = metric.int_buckets();
  uint32_t num_valid_buckets;
  switch (int_buckets.buckets_case()) {
    case IntegerBuckets::kExponential:
      num_valid_buckets = int_buckets.exponential().num_buckets();
      break;
    case IntegerBuckets::kLinear:
      num_valid_buckets = int_buckets.linear().num_buckets();
      break;
    case IntegerBuckets::BUCKETS_NOT_SET:
      LOG(ERROR) << "Invalid Cobalt config: Metric "
                 << event_record.project_context()->FullMetricName(metric)
                 << " has an invalid |int_buckets| field. Either exponential "
                    "or linear buckets must be specified.";
      return kInvalidConfig;
  }

  // In addition to the specified num_buckets, there are the underflow and
  // overflow buckets.
  num_valid_buckets += 2;

  size_t num_provided_buckets = int_histogram_event.buckets_size();
  for (auto i = 0u; i < num_provided_buckets; i++) {
    if (int_histogram_event.buckets(i).index() >= num_valid_buckets) {
      LOG(ERROR) << "The provided histogram is invalid. The index value of "
                 << int_histogram_event.buckets(i).index() << " in position " << i
                 << " is out of bounds for Metric "
                 << event_record.project_context()->FullMetricName(metric) << ".";
      return kInvalidArguments;
    }
  }

  return kOK;
}

Encoder::Result IntHistogramEventLogger::MaybeEncodeImmediateObservation(
    const ReportDefinition& report, bool may_invalidate, EventRecord* event_record) {
  TRACE_DURATION("cobalt_core", "IntHistogramEventLogger::MaybeEncodeImmediateObservation");
  const MetricDefinition& metric = *(event_record->metric());
  const Event& event = *(event_record->event());
  CHECK(event.has_int_histogram_event());
  auto* int_histogram_event = event_record->event()->mutable_int_histogram_event();
  switch (report.report_type()) {
    // Each report type has its own logic for generating immediate
    // observations.
    case ReportDefinition::INT_RANGE_HISTOGRAM: {
      HistogramPtr histogram = std::make_unique<RepeatedPtrField<HistogramBucket>>();
      if (may_invalidate) {
        // We move the buckets out of |int_histogram_event| thereby
        // invalidating that variable.
        histogram->Swap(int_histogram_event->mutable_buckets());
      } else {
        histogram->CopyFrom(int_histogram_event->buckets());
      }
      return encoder()->EncodeHistogramObservation(
          event_record->project_context()->RefMetric(&metric), &report, event.day_index(),
          int_histogram_event->event_code(), int_histogram_event->component(),
          std::move(histogram));
    }

    default:
      return BadReportType(event_record->project_context()->FullMetricName(metric), report);
  }
}

///////////// OccurrenceEventLogger method implementations //////////////////////////

Status OccurrenceEventLogger::ValidateEvent(const EventRecord& event_record) {
  if (!event_record.event()->has_occurrence_event()) {
    LOG(ERROR) << "The provided event is invalid, expected it to contain an event type of "
                  "OccurrenceEvent, but instead found "
               << event_record.event()->type_case();
    return kInvalidArguments;
  }
  if (event_record.metric() == nullptr) {
    LOG(ERROR) << "The provided event is missing a metric";
    return kInvalidArguments;
  }
  const MetricDefinition& metric = *(event_record.metric());
  return ValidateEventCodes(metric, event_record.event()->occurrence_event().event_code(),
                            event_record.project_context()->FullMetricName(metric));
}

Status OccurrenceEventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                          const EventRecord& event_record) {
  switch (report.report_type()) {
    case ReportDefinition::FLEETWIDE_OCCURRENCE_COUNTS:
    case ReportDefinition::UNIQUE_DEVICE_COUNTS:
    case ReportDefinition::UNIQUE_DEVICE_HISTOGRAMS:
    case ReportDefinition::HOURLY_VALUE_HISTOGRAMS:
    case ReportDefinition::UNIQUE_DEVICE_NUMERIC_STATS:
    case ReportDefinition::HOURLY_VALUE_NUMERIC_STATS: {
      const cobalt::util::Status status = local_aggregation()->AddEvent(event_record);
      if (!status.ok()) {
        LOG(ERROR) << "Error occurred while locally aggregating Occurrence event: "
                   << status.error_message();
      }
      return FromStatus(status);
    }
    default:
      return Status::kInvalidArguments;
  }
}

///////////// IntegerEventLogger method implementations //////////////////////////

Status IntegerEventLogger::ValidateEvent(const EventRecord& event_record) {
  if (!event_record.event()->has_integer_event()) {
    LOG(ERROR) << "The provided event is invalid, expected it to contain an event type of "
                  "IntegerEvent, but instead found "
               << event_record.event()->type_case();
    return kInvalidArguments;
  }
  if (event_record.metric() == nullptr) {
    LOG(ERROR) << "The provided event is missing a metric";
    return kInvalidArguments;
  }
  const MetricDefinition& metric = *(event_record.metric());
  return ValidateEventCodes(metric, event_record.event()->integer_event().event_code(),
                            event_record.project_context()->FullMetricName(metric));
}

Status IntegerEventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                       const EventRecord& event_record) {
  switch (report.report_type()) {
    case ReportDefinition::UNIQUE_DEVICE_HISTOGRAMS:
    case ReportDefinition::HOURLY_VALUE_HISTOGRAMS:
    case ReportDefinition::FLEETWIDE_HISTOGRAMS:
    case ReportDefinition::FLEETWIDE_MEANS:
    case ReportDefinition::UNIQUE_DEVICE_NUMERIC_STATS:
    case ReportDefinition::HOURLY_VALUE_NUMERIC_STATS: {
      const cobalt::util::Status status = local_aggregation()->AddEvent(event_record);
      if (!status.ok()) {
        LOG(ERROR) << "Error occurred while locally aggregating Integer event: "
                   << status.error_message();
      }
      return FromStatus(status);
    }
    default:
      return Status::kInvalidArguments;
  }
}

///////////// IntegerHistogramEventLogger method implementations //////////////////////////

Status IntegerHistogramEventLogger::ValidateEvent(const EventRecord& event_record) {
  if (!event_record.event()->has_integer_histogram_event()) {
    LOG(ERROR) << "The provided event is invalid, expected it to contain an event type of "
                  "IntegerHistogramEvent, but instead found "
               << event_record.event()->type_case();
    return kInvalidArguments;
  }
  const IntegerHistogramEvent& integer_histogram_event =
      event_record.event()->integer_histogram_event();
  if (event_record.metric() == nullptr) {
    LOG(ERROR) << "The provided event is missing a metric";
    return kInvalidArguments;
  }
  const MetricDefinition& metric = *(event_record.metric());

  auto status = ValidateEventCodes(metric, integer_histogram_event.event_code(),
                                   event_record.project_context()->FullMetricName(metric));
  if (status != kOK) {
    return status;
  }

  if (!metric.has_int_buckets()) {
    LOG(ERROR) << "Invalid Cobalt config: Metric "
               << event_record.project_context()->FullMetricName(metric)
               << " does not have an |int_buckets| field set.";
    return kInvalidConfig;
  }
  const IntegerBuckets& int_buckets = metric.int_buckets();
  uint32_t num_valid_buckets;
  switch (int_buckets.buckets_case()) {
    case IntegerBuckets::kExponential:
      num_valid_buckets = int_buckets.exponential().num_buckets();
      break;
    case IntegerBuckets::kLinear:
      num_valid_buckets = int_buckets.linear().num_buckets();
      break;
    case IntegerBuckets::BUCKETS_NOT_SET:
      LOG(ERROR) << "Invalid Cobalt config: Metric "
                 << event_record.project_context()->FullMetricName(metric)
                 << " has an invalid |int_buckets| field. Either exponential "
                    "or linear buckets must be specified.";
      return kInvalidConfig;
  }

  // In addition to the specified num_buckets, there are the underflow and
  // overflow buckets.
  num_valid_buckets += 2;

  size_t num_provided_buckets = integer_histogram_event.buckets_size();
  for (auto i = 0u; i < num_provided_buckets; ++i) {
    if (integer_histogram_event.buckets(i).index() >= num_valid_buckets) {
      LOG(ERROR) << "The provided histogram is invalid. The index value of "
                 << integer_histogram_event.buckets(i).index() << " in position " << i
                 << " is out of bounds for Metric "
                 << event_record.project_context()->FullMetricName(metric) << ".";
      return kInvalidArguments;
    }
  }

  return kOK;
}

Status IntegerHistogramEventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                                const EventRecord& event_record) {
  switch (report.report_type()) {
    case ReportDefinition::FLEETWIDE_HISTOGRAMS: {
      const cobalt::util::Status status = local_aggregation()->AddEvent(event_record);
      if (!status.ok()) {
        LOG(ERROR) << "Error occurred while locally aggregating IntegerHistogram event: "
                   << status.error_message();
      }
      return FromStatus(status);
    }
    default:
      return Status::kInvalidArguments;
  }
}

///////////// StringEventLogger method implementations //////////////////////////

Status StringEventLogger::ValidateEvent(const EventRecord& event_record) {
  if (!event_record.event()->has_string_event()) {
    LOG(ERROR) << "The provided event is invalid, expected it to contain an event type of "
                  "StringEvent, but instead found "
               << event_record.event()->type_case();
    return kInvalidArguments;
  }
  if (event_record.metric() == nullptr) {
    LOG(ERROR) << "The provided event is missing a metric";
    return kInvalidArguments;
  }
  const MetricDefinition& metric = *(event_record.metric());
  return ValidateEventCodes(metric, event_record.event()->string_event().event_code(),
                            event_record.project_context()->FullMetricName(metric));
}

Status StringEventLogger::MaybeUpdateLocalAggregation(const ReportDefinition& report,
                                                      const EventRecord& event_record) {
  switch (report.report_type()) {
    case ReportDefinition::STRING_COUNTS: {
      const cobalt::util::Status status = local_aggregation()->AddEvent(event_record);
      if (!status.ok()) {
        LOG(ERROR) << "Error occurred while locally aggregating String event: "
                   << status.error_message();
      }
      return FromStatus(status);
    }
    default:
      return Status::kInvalidArguments;
  }
}

/////////////// CustomEventLogger method implementations ///////////////////////

Status CustomEventLogger::ValidateEvent(const EventRecord& /*event_record*/) {
  // TODO(ninai) Add proto validation.
  return kOK;
}

Encoder::Result CustomEventLogger::MaybeEncodeImmediateObservation(const ReportDefinition& report,
                                                                   bool may_invalidate,
                                                                   EventRecord* event_record) {
  TRACE_DURATION("cobalt_core", "CustomEventLogger::MaybeEncodeImmediateObservation");
  const MetricDefinition& metric = *(event_record->metric());
  const Event& event = *(event_record->event());
  CHECK(event.has_custom_event());
  auto* custom_event = event_record->event()->mutable_custom_event();
  switch (report.report_type()) {
    // Each report type has its own logic for generating immediate
    // observations.
    case ReportDefinition::CUSTOM_RAW_DUMP: {
      EventValuesPtr event_values =
          std::make_unique<google::protobuf::Map<std::string, CustomDimensionValue>>();
      if (may_invalidate) {
        // We move the contents out of |custom_event| thereby invalidating
        // that variable.
        event_values->swap(*(custom_event->mutable_values()));
      } else {
        event_values = std::make_unique<google::protobuf::Map<std::string, CustomDimensionValue>>(
            custom_event->values());
      }
      return encoder()->EncodeCustomObservation(event_record->project_context()->RefMetric(&metric),
                                                &report, event.day_index(),
                                                std::move(event_values));
    }

    default:
      return BadReportType(event_record->project_context()->FullMetricName(metric), report);
  }
}

}  // namespace cobalt::logger::internal
