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

#include <memory>
#include <string>

#include "google/protobuf/repeated_field.h"
#include "src/logger/event_loggers.h"
#include "src/logger/event_record.h"
#include "src/logger/status.h"
#include "src/logging.h"
#include "src/registry/metric_definition.pb.h"
#include "src/registry/report_definition.pb.h"

namespace cobalt::logger {

using local_aggregation::EventAggregator;

using LoggerMethod = PerProjectLoggerCallsMadeMetricDimensionLoggerMethod;

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

Logger::Logger(std::unique_ptr<ProjectContext> project_context, const Encoder* encoder,
               EventAggregator* event_aggregator,
               local_aggregation::LocalAggregation* local_aggregation,
               ObservationWriter* observation_writer, system_data::SystemDataInterface* system_data,
               bool enable_replacement_metrics, LoggerInterface* internal_logger)
    : Logger(std::move(project_context), encoder, event_aggregator, local_aggregation,
             observation_writer, system_data, nullptr, std::weak_ptr<UndatedEventManager>(),
             enable_replacement_metrics, internal_logger) {}

Logger::Logger(std::unique_ptr<ProjectContext> project_context, const Encoder* encoder,
               EventAggregator* event_aggregator,
               local_aggregation::LocalAggregation* local_aggregation,
               ObservationWriter* observation_writer, system_data::SystemDataInterface* system_data,
               util::ValidatedClockInterface* validated_clock,
               std::weak_ptr<UndatedEventManager> undated_event_manager,
               bool enable_replacement_metrics, LoggerInterface* internal_logger)
    : project_context_(std::move(project_context)),
      encoder_(encoder),
      event_aggregator_(event_aggregator),
      local_aggregation_(local_aggregation),
      observation_writer_(observation_writer),
      system_data_(system_data),
      validated_clock_(validated_clock),
      undated_event_manager_(std::move(undated_event_manager)),
      enable_replacement_metrics_(enable_replacement_metrics) {
  CHECK(project_context_);
  CHECK(encoder_);
  CHECK(event_aggregator_);
  CHECK(local_aggregation_);
  CHECK(observation_writer_);
  if (!validated_clock_) {
    local_validated_clock_ =
        std::make_unique<util::AlwaysAccurateClock>(std::make_unique<util::SystemClock>());
    validated_clock_ = local_validated_clock_.get();
  }
  if (internal_logger) {
    // If we were passed an internal Logger then we are not an internal Logger.
    is_internal_logger_ = false;
    internal_metrics_ = std::make_unique<InternalMetricsImpl>(internal_logger);
  } else {
    // If we were not passed an internal Logger then we are an internal Logger.
    is_internal_logger_ = true;
    internal_metrics_ = std::make_unique<NoOpInternalMetrics>();
  }
  if (event_aggregator_->UpdateAggregationConfigs(*project_context_) != kOK) {
    LOG(ERROR) << "Failed to provide aggregation configurations to the "
                  "EventAggregator.";
  }
}

Status Logger::LogEvent(uint32_t metric_id, uint32_t event_code) {
  auto event_record = std::make_unique<EventRecord>(project_context_, metric_id);
  Status replacement_status = kOK;
  if (event_record->metric()->replacement_metric_id() != 0 && enable_replacement_metrics_) {
    PauseInternalLogging();
    auto replacement_event_record = std::make_unique<EventRecord>(
        project_context_, event_record->metric()->replacement_metric_id());
    switch (replacement_event_record->metric()->metric_type()) {
      case MetricDefinition::OCCURRENCE: {
        replacement_status =
            LogOccurrence(replacement_event_record->metric()->id(), 1, {event_code});
        if (replacement_status != kOK) {
          LOG(WARNING) << "Failed to log replacement metric "
                       << replacement_event_record->FullMetricName() << " for metric "
                       << event_record->FullMetricName() << ": " << replacement_status;
        }
      } break;
      default:
        replacement_status = kInvalidConfig;
        LOG(WARNING) << "Unable to log replacement metric "
                     << replacement_event_record->FullMetricName() << " for metric "
                     << event_record->FullMetricName() << ": " << replacement_status;
        break;
    }
    ResumeInternalLogging();
  }
  internal_metrics_->LoggerCalled(LoggerMethod::LogEvent, project_context_->project());
  auto* event_occurred_event = event_record->event()->mutable_event_occurred_event();
  event_occurred_event->set_event_code(event_code);
  Status status = Log(metric_id, MetricDefinition::EVENT_OCCURRED, std::move(event_record));
  if (replacement_status != kOK) {
    return replacement_status;
  }
  return status;
}

Status Logger::LogEventCount(uint32_t metric_id, const std::vector<uint32_t>& event_codes,
                             const std::string& component, int64_t period_duration_micros,
                             uint32_t count) {
  internal_metrics_->LoggerCalled(LoggerMethod::LogEventCount, project_context_->project());
  auto event_record = std::make_unique<EventRecord>(project_context_, metric_id);
  Status replacement_status = kOK;
  if (event_record->metric()->replacement_metric_id() != 0 && enable_replacement_metrics_) {
    PauseInternalLogging();
    auto replacement_event_record = std::make_unique<EventRecord>(
        project_context_, event_record->metric()->replacement_metric_id());
    switch (replacement_event_record->metric()->metric_type()) {
      case MetricDefinition::OCCURRENCE: {
        replacement_status =
            LogOccurrence(replacement_event_record->metric()->id(), count, event_codes);
        if (replacement_status != kOK) {
          LOG(WARNING) << "Failed to log replacement metric "
                       << replacement_event_record->FullMetricName() << " for metric "
                       << event_record->FullMetricName() << ": " << replacement_status;
        }
      } break;
      case MetricDefinition::STRING: {
        for (int i = 0; i < count; i++) {
          replacement_status =
              LogString(replacement_event_record->metric()->id(), component, event_codes);
          if (replacement_status != kOK) {
            LOG(WARNING) << "Failed to log replacement metric "
                         << replacement_event_record->FullMetricName() << " for metric "
                         << event_record->FullMetricName() << ": " << replacement_status;
          }
        }

      } break;
      case MetricDefinition::INTEGER: {
        replacement_status =
            LogInteger(replacement_event_record->metric()->id(), count, event_codes);
        if (replacement_status != kOK) {
          LOG(WARNING) << "Failed to log replacement metric "
                       << replacement_event_record->FullMetricName() << " for metric "
                       << event_record->FullMetricName() << ": " << replacement_status;
        }

      } break;
      default:
        replacement_status = kInvalidConfig;
        LOG(WARNING) << "Unable to log replacement metric "
                     << replacement_event_record->FullMetricName() << " for metric "
                     << event_record->FullMetricName() << ": " << replacement_status;
        break;
    }
    ResumeInternalLogging();
  }
  auto* event_count_event = event_record->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);
  Status status = Log(metric_id, MetricDefinition::EVENT_COUNT, std::move(event_record));
  if (replacement_status != kOK) {
    return replacement_status;
  }
  return status;
}

const int64_t kNanosecondsPerMicrosecond = 1000;
const int64_t kMicrosecondsPerMillisecond = 1000;
const int64_t kMicrosecondsPerSecond = kMicrosecondsPerMillisecond * 1000;
const int64_t kMicrosecondsPerMinute = kMicrosecondsPerSecond * 60;
Status Logger::LogElapsedTime(uint32_t metric_id, const std::vector<uint32_t>& event_codes,
                              const std::string& component, int64_t elapsed_micros) {
  internal_metrics_->LoggerCalled(LoggerMethod::LogElapsedTime, project_context_->project());
  auto event_record = std::make_unique<EventRecord>(project_context_, metric_id);
  Status replacement_status = kOK;
  if (event_record->metric()->replacement_metric_id() != 0 && enable_replacement_metrics_) {
    PauseInternalLogging();
    auto replacement_event_record = std::make_unique<EventRecord>(
        project_context_, event_record->metric()->replacement_metric_id());
    switch (replacement_event_record->metric()->metric_type()) {
      case MetricDefinition::INTEGER: {
        int64_t converted_value = 0;
        switch (replacement_event_record->metric()->metric_units()) {
          case cobalt::MetricUnits::NANOSECONDS:
            converted_value = elapsed_micros * kNanosecondsPerMicrosecond;
            break;
          case cobalt::MetricUnits::MICROSECONDS:
            converted_value = elapsed_micros;
            break;
          case cobalt::MetricUnits::MILLISECONDS:
            converted_value = elapsed_micros / kMicrosecondsPerMillisecond;
            break;
          case cobalt::MetricUnits::SECONDS:
            converted_value = elapsed_micros / kMicrosecondsPerSecond;
            break;
          case cobalt::MetricUnits::MINUTES:
            converted_value = elapsed_micros / kMicrosecondsPerMinute;
            break;
          default:
            // We can't reasonably convert this value, so we use the original value.
            converted_value = elapsed_micros;
            break;
        }
        replacement_status =
            LogInteger(replacement_event_record->metric()->id(), converted_value, event_codes);
        if (replacement_status != kOK) {
          LOG(WARNING) << "Failed to log replacement metric "
                       << replacement_event_record->FullMetricName() << " for metric "
                       << event_record->FullMetricName() << ": " << replacement_status;
        }
      } break;
      default:
        replacement_status = kInvalidConfig;
        LOG(WARNING) << "Unable to log replacement metric "
                     << replacement_event_record->FullMetricName() << " for metric "
                     << event_record->FullMetricName() << ": " << replacement_status;
        break;
    }
    ResumeInternalLogging();
  }
  auto* elapsed_time_event = event_record->event()->mutable_elapsed_time_event();
  CopyEventCodesAndComponent(event_codes, component, elapsed_time_event);
  elapsed_time_event->set_elapsed_micros(elapsed_micros);
  Status status = Log(metric_id, MetricDefinition::ELAPSED_TIME, std::move(event_record));
  if (replacement_status != kOK) {
    return replacement_status;
  }
  return status;
}

Status Logger::LogFrameRate(uint32_t metric_id, const std::vector<uint32_t>& event_codes,
                            const std::string& component, float fps) {
  internal_metrics_->LoggerCalled(LoggerMethod::LogFrameRate, project_context_->project());
  auto event_record = std::make_unique<EventRecord>(project_context_, metric_id);
  Status replacement_status = kOK;
  if (event_record->metric()->replacement_metric_id() != 0 && enable_replacement_metrics_) {
    PauseInternalLogging();
    auto replacement_event_record = std::make_unique<EventRecord>(
        project_context_, event_record->metric()->replacement_metric_id());
    switch (replacement_event_record->metric()->metric_type()) {
      case MetricDefinition::INTEGER: {
        replacement_status =
            // NOLINTNEXTLINE readability-magic-numbers
            LogInteger(replacement_event_record->metric()->id(), std::round(fps * 1000.0),
                       event_codes);
        if (replacement_status != kOK) {
          LOG(WARNING) << "Failed to log replacement metric "
                       << replacement_event_record->FullMetricName() << " for metric "
                       << event_record->FullMetricName() << ": " << replacement_status;
        }
        break;
      }
      default:
        replacement_status = kInvalidConfig;
        LOG(WARNING) << "Unable to log replacement metric "
                     << replacement_event_record->FullMetricName() << " for metric "
                     << event_record->FullMetricName() << ": " << replacement_status;
        break;
    }
    ResumeInternalLogging();
  }
  auto* frame_rate_event = event_record->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));
  Status status = Log(metric_id, MetricDefinition::FRAME_RATE, std::move(event_record));
  if (replacement_status != kOK) {
    return replacement_status;
  }
  return status;
}

Status Logger::LogMemoryUsage(uint32_t metric_id, const std::vector<uint32_t>& event_codes,
                              const std::string& component, int64_t bytes) {
  internal_metrics_->LoggerCalled(LoggerMethod::LogMemoryUsage, project_context_->project());
  auto event_record = std::make_unique<EventRecord>(project_context_, metric_id);
  Status replacement_status = kOK;
  if (event_record->metric()->replacement_metric_id() != 0 && enable_replacement_metrics_) {
    PauseInternalLogging();
    auto replacement_event_record = std::make_unique<EventRecord>(
        project_context_, event_record->metric()->replacement_metric_id());
    switch (replacement_event_record->metric()->metric_type()) {
      case MetricDefinition::INTEGER: {
        replacement_status =
            LogInteger(replacement_event_record->metric()->id(), bytes, event_codes);
        if (replacement_status != kOK) {
          LOG(WARNING) << "Failed to log replacement metric "
                       << replacement_event_record->FullMetricName() << " for metric "
                       << event_record->FullMetricName() << ": " << replacement_status;
        }
        break;
      }
      default:
        replacement_status = kInvalidConfig;
        LOG(WARNING) << "Unable to log replacement metric "
                     << replacement_event_record->FullMetricName() << " for metric "
                     << event_record->FullMetricName() << ": " << replacement_status;
        break;
    }
    ResumeInternalLogging();
  }
  auto* memory_usage_event = event_record->event()->mutable_memory_usage_event();
  CopyEventCodesAndComponent(event_codes, component, memory_usage_event);
  memory_usage_event->set_bytes(bytes);
  Status status = Log(metric_id, MetricDefinition::MEMORY_USAGE, std::move(event_record));
  if (replacement_status != kOK) {
    return replacement_status;
  }
  return status;
}

Status Logger::LogIntHistogram(uint32_t metric_id, const std::vector<uint32_t>& event_codes,
                               const std::string& component, HistogramPtr histogram) {
  internal_metrics_->LoggerCalled(LoggerMethod::LogIntHistogram, project_context_->project());
  auto event_record = std::make_unique<EventRecord>(project_context_, metric_id);
  Status replacement_status = kOK;
  if (event_record->metric()->replacement_metric_id() != 0 && enable_replacement_metrics_) {
    PauseInternalLogging();
    auto replacement_event_record = std::make_unique<EventRecord>(
        project_context_, event_record->metric()->replacement_metric_id());
    switch (replacement_event_record->metric()->metric_type()) {
      case MetricDefinition::INTEGER_HISTOGRAM: {
        auto histogram_copy =
            std::make_unique<google::protobuf::RepeatedPtrField<cobalt::HistogramBucket>>();
        histogram_copy->CopyFrom(*histogram.get());
        replacement_status = LogIntegerHistogram(replacement_event_record->metric()->id(),
                                                 std::move(histogram_copy), event_codes);
        if (replacement_status != kOK) {
          LOG(WARNING) << "Failed to log replacement metric "
                       << replacement_event_record->FullMetricName() << " for metric "
                       << event_record->FullMetricName() << ": " << replacement_status;
        }
        break;
      }
      default:
        replacement_status = kInvalidConfig;
        LOG(WARNING) << "Unable to log replacement metric "
                     << replacement_event_record->FullMetricName() << " for metric "
                     << event_record->FullMetricName() << ": " << replacement_status;
        break;
    }
    ResumeInternalLogging();
  }
  auto* int_histogram_event = event_record->event()->mutable_int_histogram_event();
  CopyEventCodesAndComponent(event_codes, component, int_histogram_event);
  int_histogram_event->mutable_buckets()->Swap(histogram.get());
  Status status = Log(metric_id, MetricDefinition::INT_HISTOGRAM, std::move(event_record));
  if (replacement_status != kOK) {
    return replacement_status;
  }
  return status;
}

Status Logger::LogOccurrence(uint32_t metric_id, uint64_t count,
                             const std::vector<uint32_t>& event_codes) {
  internal_metrics_->LoggerCalled(LoggerMethod::LogOccurrence, project_context_->project());
  auto event_record = std::make_unique<EventRecord>(project_context_, metric_id);
  OccurrenceEvent* occurrence_event = event_record->event()->mutable_occurrence_event();
  CopyEventCodes(event_codes, occurrence_event);
  occurrence_event->set_count(count);
  return Log(metric_id, MetricDefinition::OCCURRENCE, std::move(event_record));
}

Status Logger::LogInteger(uint32_t metric_id, int64_t value,
                          const std::vector<uint32_t>& event_codes) {
  internal_metrics_->LoggerCalled(LoggerMethod::LogInteger, project_context_->project());
  auto event_record = std::make_unique<EventRecord>(project_context_, metric_id);
  IntegerEvent* integer_event = event_record->event()->mutable_integer_event();
  CopyEventCodes(event_codes, integer_event);
  integer_event->set_value(value);
  return Log(metric_id, MetricDefinition::INTEGER, std::move(event_record));
}

Status Logger::LogIntegerHistogram(uint32_t metric_id, HistogramPtr histogram,
                                   const std::vector<uint32_t>& event_codes) {
  internal_metrics_->LoggerCalled(LoggerMethod::LogIntegerHistogram, project_context_->project());
  auto event_record = std::make_unique<EventRecord>(project_context_, metric_id);
  IntegerHistogramEvent* integer_histogram_event =
      event_record->event()->mutable_integer_histogram_event();
  CopyEventCodes(event_codes, integer_histogram_event);
  integer_histogram_event->mutable_buckets()->Swap(histogram.get());
  return Log(metric_id, MetricDefinition::INTEGER_HISTOGRAM, std::move(event_record));
}

Status Logger::LogString(uint32_t metric_id, const std::string& string_value,
                         const std::vector<uint32_t>& event_codes) {
  internal_metrics_->LoggerCalled(LoggerMethod::LogString, project_context_->project());
  auto event_record = std::make_unique<EventRecord>(project_context_, metric_id);
  StringEvent* string_event = event_record->event()->mutable_string_event();
  CopyEventCodes(event_codes, string_event);
  string_event->set_string_value(string_value);
  return Log(metric_id, MetricDefinition::STRING, std::move(event_record));
}

Status Logger::LogCustomEvent(uint32_t metric_id, EventValuesPtr event_values) {
  internal_metrics_->LoggerCalled(LoggerMethod::LogCustomEvent, project_context_->project());
  auto event_record = std::make_unique<EventRecord>(project_context_, metric_id);
  auto* custom_event = event_record->event()->mutable_custom_event();
  custom_event->mutable_values()->swap(*event_values);
  return Log(metric_id, MetricDefinition::CUSTOM, std::move(event_record));
}

Status Logger::LogSerializedCustomEvent(uint32_t metric_id,
                                        std::unique_ptr<std::string> serialized_proto) {
  internal_metrics_->LoggerCalled(LoggerMethod::LogSerializedCustomEvent,
                                  project_context_->project());
  auto event_record = std::make_unique<EventRecord>(project_context_, metric_id);
  auto* custom_event = event_record->event()->mutable_custom_event();
  custom_event->mutable_serialized_proto()->swap(*serialized_proto);
  return Log(metric_id, MetricDefinition::CUSTOM, std::move(event_record));
}

Status Logger::Log(uint32_t metric_id, MetricDefinition::MetricType metric_type,
                   std::unique_ptr<EventRecord> event_record) {
  const int kVerboseLoggingLevel = (is_internal_logger_ ? 9 : 7);
  VLOG(kVerboseLoggingLevel) << "Received logged event for " << event_record->FullMetricName();
  auto event_logger =
      internal::EventLogger::Create(metric_type, encoder_, event_aggregator_, local_aggregation_,
                                    observation_writer_, system_data_);
  Status validation_result =
      event_logger->PrepareAndValidateEvent(metric_id, metric_type, event_record.get());
  if (validation_result != kOK) {
    return validation_result;
  }

  auto now = validated_clock_->now();
  if (!now) {
    VLOG(kVerboseLoggingLevel)
        << "Buffering logged event because we don't yet have an accurate clock. ";
    // Missing system time means that the clock is not valid, so save the event until it is.
    auto undated_event_manager = undated_event_manager_.lock();
    if (undated_event_manager) {
      return undated_event_manager->Save(std::move(event_record));
    }
    // A missing UndatedEventManager is handled by retrying the clock, which should now be valid.

    // If we fall through to here, then a race condition has occurred in which the clock that we
    // thought was not validated, has become validated. Retrying the clock should succeed.
    now = validated_clock_->now();
    if (!now) {
      // This should never happen, if it does then it's a bug.
      LOG(ERROR) << "Clock is invalid but there is no UndatedEventManager that will save the "
                    "event, dropping event for metric: "
                 << metric_id;
      return Status::kOther;
    }
  }

  return event_logger->Log(std::move(event_record), *now);
}

void Logger::PauseInternalLogging() { internal_metrics_->PauseLogging(); }
void Logger::ResumeInternalLogging() { internal_metrics_->ResumeLogging(); }

}  // namespace cobalt::logger
