// 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/cobalt/bin/app/logger_impl.h"

#include <lib/trace/event.h>

#include "src/cobalt/bin/app/utils.h"

namespace cobalt {

LoggerImpl::LoggerImpl(std::unique_ptr<logger::LoggerInterface> logger, TimerManager* timer_manager)
    : logger_(std::move(logger)), timer_manager_(timer_manager) {}

void LoggerImpl::LogEvent(uint32_t metric_id, uint32_t event_code,
                          fuchsia::cobalt::LoggerBase::LogEventCallback callback) {
  TRACE_DURATION("cobalt_fidl", "LoggerImpl::LogEvent");
  callback(ToCobaltStatus(logger_->LogEvent(metric_id, event_code)));
}

void LoggerImpl::LogEventCount(uint32_t metric_id, uint32_t event_code, std::string component,
                               int64_t period_duration_micros, int64_t count,
                               fuchsia::cobalt::LoggerBase::LogEventCountCallback callback) {
  TRACE_DURATION("cobalt_fidl", "LoggerImpl::LogEventCount");
  callback(ToCobaltStatus(
      logger_->LogEventCount(metric_id, event_code, component, period_duration_micros, count)));
}

void LoggerImpl::LogElapsedTime(uint32_t metric_id, uint32_t event_code, std::string component,
                                int64_t elapsed_micros,
                                fuchsia::cobalt::LoggerBase::LogElapsedTimeCallback callback) {
  TRACE_DURATION("cobalt_fidl", "LoggerImpl::LogElapsedTime");
  callback(
      ToCobaltStatus(logger_->LogElapsedTime(metric_id, event_code, component, elapsed_micros)));
}

void LoggerImpl::LogFrameRate(uint32_t metric_id, uint32_t event_code, std::string component,
                              float fps,
                              fuchsia::cobalt::LoggerBase::LogFrameRateCallback callback) {
  TRACE_DURATION("cobalt_fidl", "LoggerImpl::LogFrameRate");
  callback(ToCobaltStatus(logger_->LogFrameRate(metric_id, event_code, component, fps)));
}

void LoggerImpl::LogMemoryUsage(uint32_t metric_id, uint32_t event_code, std::string component,
                                int64_t bytes,
                                fuchsia::cobalt::LoggerBase::LogMemoryUsageCallback callback) {
  TRACE_DURATION("cobalt_fidl", "LoggerImpl::LogMemoryUsage");
  callback(ToCobaltStatus(logger_->LogMemoryUsage(metric_id, event_code, component, bytes)));
}

void LoggerImpl::LogIntHistogram(uint32_t metric_id, uint32_t event_code, std::string component,
                                 std::vector<fuchsia::cobalt::HistogramBucket> histogram,
                                 fuchsia::cobalt::Logger::LogIntHistogramCallback callback) {
  TRACE_DURATION("cobalt_fidl", "LoggerImpl::LogIntHistogram");
  logger::HistogramPtr histogram_ptr(new google::protobuf::RepeatedPtrField<HistogramBucket>());
  for (auto it = histogram.begin(); histogram.end() != it; it++) {
    auto bucket = histogram_ptr->Add();
    bucket->set_index((*it).index);
    bucket->set_count((*it).count);
  }
  callback(ToCobaltStatus(
      logger_->LogIntHistogram(metric_id, event_code, component, std::move(histogram_ptr))));
}

void LoggerImpl::LogIntHistogram(uint32_t metric_id, uint32_t event_code, std::string component,
                                 std::vector<uint32_t> bucket_indices,
                                 std::vector<uint64_t> bucket_counts,
                                 fuchsia::cobalt::LoggerSimple::LogIntHistogramCallback callback) {
  TRACE_DURATION("cobalt_fidl", "LoggerImpl::LogIntHistogram");
  if (bucket_indices.size() != bucket_counts.size()) {
    FX_LOGS(ERROR) << "[" << metric_id << "]: bucket_indices.size() != bucket_counts.size().";
    callback(Status::INVALID_ARGUMENTS);
    return;
  }
  logger::HistogramPtr histogram_ptr(new google::protobuf::RepeatedPtrField<HistogramBucket>());
  for (auto i = 0; i < bucket_indices.size(); i++) {
    auto bucket = histogram_ptr->Add();
    bucket->set_index(bucket_indices.at(i));
    bucket->set_count(bucket_counts.at(i));
  }

  callback(ToCobaltStatus(
      logger_->LogIntHistogram(metric_id, event_code, component, std::move(histogram_ptr))));
}

void LoggerImpl::LogCustomEvent(uint32_t metric_id,
                                std::vector<fuchsia::cobalt::CustomEventValue> event_values,
                                fuchsia::cobalt::Logger::LogCustomEventCallback callback) {
  TRACE_DURATION("cobalt_fidl", "LoggerImpl::LogCustomEvent");
  logger::EventValuesPtr inner_event_values(
      new google::protobuf::Map<std::string, CustomDimensionValue>());
  for (auto it = event_values.begin(); event_values.end() != it; it++) {
    CustomDimensionValue value;
    if (it->value.is_string_value()) {
      value.set_string_value(it->value.string_value());
    } else if (it->value.is_int_value()) {
      value.set_int_value(it->value.int_value());
    } else if (it->value.is_double_value()) {
      value.set_double_value(it->value.double_value());
    } else if (it->value.is_index_value()) {
      value.set_index_value(it->value.index_value());
    }

    auto pair = google::protobuf::MapPair(it->dimension_name, value);
    inner_event_values->insert(pair);
  }
  callback(ToCobaltStatus(logger_->LogCustomEvent(metric_id, std::move(inner_event_values))));
}

template <class CB>
void LoggerImpl::AddTimerObservationIfReady(std::unique_ptr<TimerVal> timer_val_ptr, CB callback) {
  if (!TimerManager::isReady(timer_val_ptr)) {
    // TimerManager has not received both StartTimer and EndTimer calls. Return
    // OK status and wait for the other call.
    callback(Status::OK);
    return;
  }

  callback(ToCobaltStatus(logger_->LogElapsedTime(
      timer_val_ptr->metric_id, timer_val_ptr->event_code, timer_val_ptr->component,
      timer_val_ptr->end_timestamp - timer_val_ptr->start_timestamp)));
}

void LoggerImpl::StartTimer(uint32_t metric_id, uint32_t event_code, std::string component,
                            std::string timer_id, uint64_t timestamp, uint32_t timeout_s,
                            fuchsia::cobalt::LoggerBase::StartTimerCallback callback) {
  if (!timer_manager_) {
    FX_LOGS(ERROR) << "Cobalt internal error: StartTimer() invoked but there is no TimerManager";
    callback(Status::INTERNAL_ERROR);
    return;
  }
  std::unique_ptr<TimerVal> timer_val_ptr;
  auto status = timer_manager_->GetTimerValWithStart(metric_id, event_code, component, 0, timer_id,
                                                     timestamp, timeout_s, &timer_val_ptr);

  if (status != Status::OK) {
    callback(status);
    return;
  }

  AddTimerObservationIfReady(std::move(timer_val_ptr), std::move(callback));
}

void LoggerImpl::EndTimer(std::string timer_id, uint64_t timestamp, uint32_t timeout_s,
                          fuchsia::cobalt::LoggerBase::EndTimerCallback callback) {
  if (!timer_manager_) {
    FX_LOGS(ERROR) << "Cobalt internal error: EndTimer() invoked but there is no TimerManager";
    callback(Status::INTERNAL_ERROR);
    return;
  }
  std::unique_ptr<TimerVal> timer_val_ptr;
  auto status = timer_manager_->GetTimerValWithEnd(timer_id, timestamp, timeout_s, &timer_val_ptr);

  if (status != Status::OK) {
    callback(status);
    return;
  }

  AddTimerObservationIfReady(std::move(timer_val_ptr), std::move(callback));
}

using fuchsia::cobalt::EventPayload;
void LoggerImpl::LogCobaltEvent(fuchsia::cobalt::CobaltEvent event,
                                fuchsia::cobalt::Logger::LogCobaltEventCallback callback) {
  TRACE_DURATION("cobalt_fidl", "LoggerImpl::LogCobaltEvent");

  switch (event.payload.Which()) {
    case EventPayload::Tag::kEvent:
      if (event.event_codes.size() != 1) {
        callback(Status::INVALID_ARGUMENTS);
      } else {
        callback(ToCobaltStatus(logger_->LogEvent(event.metric_id, event.event_codes[0])));
      }
      return;

    case EventPayload::Tag::kEventCount:
      callback(ToCobaltStatus(logger_->LogEventCount(
          event.metric_id, event.event_codes, event.component.value_or(""),
          event.payload.event_count().period_duration_micros, event.payload.event_count().count)));
      return;

    case EventPayload::Tag::kElapsedMicros:
      callback(ToCobaltStatus(logger_->LogElapsedTime(event.metric_id, event.event_codes,
                                                      event.component.value_or(""),
                                                      event.payload.elapsed_micros())));
      return;

    case EventPayload::Tag::kFps:
      callback(ToCobaltStatus(logger_->LogFrameRate(
          event.metric_id, event.event_codes, event.component.value_or(""), event.payload.fps())));
      return;

    case EventPayload::Tag::kMemoryBytesUsed:
      callback(ToCobaltStatus(logger_->LogMemoryUsage(event.metric_id, event.event_codes,
                                                      event.component.value_or(""),
                                                      event.payload.memory_bytes_used())));
      return;

    case EventPayload::Tag::kIntHistogram: {
      auto histogram = std::move(event.payload.int_histogram());
      logger::HistogramPtr histogram_ptr(new google::protobuf::RepeatedPtrField<HistogramBucket>());
      for (auto it = histogram.begin(); histogram.end() != it; it++) {
        auto bucket = histogram_ptr->Add();
        bucket->set_index((*it).index);
        bucket->set_count((*it).count);
      }
      callback(ToCobaltStatus(logger_->LogIntHistogram(event.metric_id, event.event_codes,
                                                       event.component.value_or(""),
                                                       std::move(histogram_ptr))));
      return;
    }

    default:
      callback(Status::INVALID_ARGUMENTS);
      return;
  }
}

void LoggerImpl::LogCobaltEvents(std::vector<fuchsia::cobalt::CobaltEvent> events,
                                 fuchsia::cobalt::Logger::LogCobaltEventCallback callback) {
  TRACE_DURATION("cobalt_fidl", "LoggerImpl::LogCobaltEvents");
  logger_->RecordLoggerCall(logger::LoggerCallsMadeMetricDimensionLoggerMethod::LogCobaltEvents);

  // tracking LoggerCalled events is expensive (~3.5ms/event). We want
  // LogCobaltEvents to be a more performance concious alternative, so we pause
  // this logging while we work through the batch.
  logger_->PauseInternalLogging();

  auto failures = 0;

  auto end = std::make_move_iterator(events.end());

  for (auto it = std::make_move_iterator(events.begin()); it != end; it++) {
    LogCobaltEvent(std::move(*it), [failures](Status status) mutable {
      if (status != Status::OK) {
        failures += 1;
      }
    });
  }

  logger_->ResumeInternalLogging();

  if (failures == 0) {
    callback(Status::OK);
  } else {
    callback(Status::INTERNAL_ERROR);
  }
}

}  // namespace cobalt
