// 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.

#ifndef COBALT_SRC_LOGGER_INTERNAL_METRICS_H_
#define COBALT_SRC_LOGGER_INTERNAL_METRICS_H_

#include <memory>
#include <queue>
#include <string>

#include "src/lib/util/protected_fields.h"
#include "src/logger/internal_metrics_config.cb.h"
#include "src/logger/logger_interface.h"
#include "src/registry/project.pb.h"

namespace cobalt::logger {

// InternalMetrics defines the methods used for collecting cobalt-internal
// metrics.
class InternalMetrics {
 public:
  // Returns a pointer to an InternalMetrics object which can be used for
  // collecting cobalt-internal metrics.
  //
  // |logger| the logger used to log internal metrics. If the pointer is null,
  // NoOpInternalMetrics will be used.
  static std::unique_ptr<InternalMetrics> NewWithLogger(LoggerInterface* logger);

  // LoggerCalled (cobalt_internal::metrics::logger_calls_made) and
  // (cobalt_internal::metrics::per_project_logger_calls_made) are logged for
  // every call to Logger along with which method was called and the project
  // that called it.
  virtual void LoggerCalled(PerProjectLoggerCallsMadeMetricDimensionLoggerMethod method,
                            const Project& project) = 0;

  // cobalt_internal::metrics::per_device_bytes_uploaded is logged when the
  // Clearcut Uploader attempts or succeeds to upload observations from the
  // device.
  virtual void BytesUploaded(PerDeviceBytesUploadedMetricDimensionStatus upload_status,
                             int64_t byte_count) = 0;

  // cobalt_internal::metrics::per_project_bytes_uploaded is logged when the
  // Shipping Manager attempts or succeeds to store observations on the device.
  virtual void BytesUploaded(PerProjectBytesUploadedMetricDimensionStatus upload_status,
                             int64_t byte_count, uint32_t customer_id, uint32_t project_id) = 0;

  // cobalt_internal::metrics::per_project_bytes_stored is logged when the
  // Observation Store attempts or succeeds to store observations on the device.
  virtual void BytesStored(PerProjectBytesStoredMetricDimensionStatus upload_status,
                           int64_t byte_count, uint32_t customer_id, uint32_t project_id) = 0;

  // cobalt_internal::metrics::idle_observation_upload is logged when the
  // Shipping Manager encrypts and uploads observations.
  virtual void IdleObservationUpload(IdleObservationUploadMetricDimensionDeviceState state) = 0;

  // cobalt_internal::metrics::inaccurate_clock_events_cached is logged when the
  // UndatedEventManager saves an event while the clock is inaccurate.
  virtual void InaccurateClockEventsCached(int64_t event_count, uint32_t customer_id,
                                           uint32_t project_id) = 0;

  // cobalt_internal::metrics::inaccurate_clock_events_dropped is logged when the
  // UndatedEventManager drops a saved event while the clock is inaccurate and it runs out of space.
  virtual void InaccurateClockEventsDropped(int64_t event_count, uint32_t customer_id,
                                            uint32_t project_id) = 0;

  // cobalt_internal::metrics::set_software_distribution_info_called is logged
  // when the SystemData receives SoftwareDistributionInfo.
  virtual void SetSoftwareDistributionInfoCalled(
      SetSoftwareDistributionInfoCalledEventCodes event_codes) = 0;

  // Used to mark which class this disk usage is coming from. Can be:
  // - ObservationStore
  // - LocalAggregateStorage
  // - AggregateStore
  // - ObservationHistory
  using StorageClass = MetricsMetricDimensionStorageClass;

  // cobalt_internal::metrics::storage_usage is used to track how much data is stored per-class on
  // disk.
  virtual void TrackDiskUsage(StorageClass storage_class, int64_t bytes, int64_t max_bytes) = 0;
  void TrackDiskUsage(StorageClass storage_class, int64_t bytes) {
    TrackDiskUsage(storage_class, bytes, -1);
  }

  // Flush queued internal metrics.
  virtual void Flush() = 0;

  // Returns true if this is an instance of the real implementation of
  // InternalMetrics that will really do internal logging and false if this
  // is a fake or no-op implementation.
  [[nodiscard]] virtual bool IsRealImpl() const = 0;

  virtual ~InternalMetrics() = default;
};

// NoOpInternalMetrics is to be used when the LoggerInterface* provided to the
// Logger constructor is nullptr. It stubs out all of the calls in the
// InternalMetrics interface, allowing code to safely make these calls even if
// no LoggerInterface* was provided.
class NoOpInternalMetrics : public InternalMetrics {
 public:
  void LoggerCalled(PerProjectLoggerCallsMadeMetricDimensionLoggerMethod method,
                    const Project& project) override {}

  void BytesUploaded(PerDeviceBytesUploadedMetricDimensionStatus upload_status,
                     int64_t byte_count) override {}

  void BytesUploaded(PerProjectBytesUploadedMetricDimensionStatus upload_status, int64_t byte_count,
                     uint32_t customer_id, uint32_t project_id) override {}

  void BytesStored(PerProjectBytesStoredMetricDimensionStatus upload_status, int64_t byte_count,
                   uint32_t customer_id, uint32_t project_id) override {}

  void IdleObservationUpload(IdleObservationUploadMetricDimensionDeviceState state) override {}

  void InaccurateClockEventsCached(int64_t event_count, uint32_t customer_id,
                                   uint32_t project_id) override {}

  void InaccurateClockEventsDropped(int64_t event_count, uint32_t customer_id,
                                    uint32_t project_id) override {}

  void SetSoftwareDistributionInfoCalled(
      SetSoftwareDistributionInfoCalledEventCodes event_codes) override {}

  void TrackDiskUsage(StorageClass storage_class, int64_t bytes, int64_t max_bytes) override {}

  void Flush() override {}

  [[nodiscard]] bool IsRealImpl() const override { return false; }

  ~NoOpInternalMetrics() override = default;
};

// InternalMetricsImpl is the actual implementation of InternalMetrics. It is a
// wrapper around the (non nullptr) LoggerInterface* that was provided to the
// Logger constructor.
class InternalMetricsImpl : public InternalMetrics {
 public:
  explicit InternalMetricsImpl(LoggerInterface* logger);

  void LoggerCalled(PerProjectLoggerCallsMadeMetricDimensionLoggerMethod method,
                    const Project& project) override;

  void BytesUploaded(PerDeviceBytesUploadedMetricDimensionStatus upload_status,
                     int64_t byte_count) override;

  void BytesUploaded(PerProjectBytesUploadedMetricDimensionStatus upload_status, int64_t byte_count,
                     uint32_t customer_id, uint32_t project_id) override;

  void BytesStored(PerProjectBytesStoredMetricDimensionStatus upload_status, int64_t byte_count,
                   uint32_t customer_id, uint32_t project_id) override;

  void IdleObservationUpload(IdleObservationUploadMetricDimensionDeviceState state) override;

  void InaccurateClockEventsCached(int64_t event_count, uint32_t customer_id,
                                   uint32_t project_id) override;

  void InaccurateClockEventsDropped(int64_t event_count, uint32_t customer_id,
                                    uint32_t project_id) override;

  void SetSoftwareDistributionInfoCalled(
      SetSoftwareDistributionInfoCalledEventCodes event_codes) override;

  void TrackDiskUsage(StorageClass storage_class, int64_t bytes, int64_t max_bytes) override;

  void Flush() override;

  [[nodiscard]] bool IsRealImpl() const override { return true; }

  ~InternalMetricsImpl() override = default;

 private:
  struct Protected {
    std::vector<std::function<void()>> queued_lambdas;
  };
  util::ProtectedFields<Protected> fields_;
  LoggerInterface* logger_;  // not owned
};

// InternalMetricsPtr holds either a pointer to an InternalMetrics implementation, or a pointer to
// an instance of NoOpInternalMetrics. This class guarantees that the pointer is always valid.
class InternalMetricsPtr {
 public:
  InternalMetricsPtr() { reset(nullptr); }
  explicit InternalMetricsPtr(InternalMetrics* internal_metrics) { reset(internal_metrics); }

  void reset(InternalMetrics* internal_metrics) {
    if (internal_metrics) {
      ptr_ = internal_metrics;
    } else {
      ptr_ = &noop_internal_metrics_;
    }
  }

  [[nodiscard]] InternalMetrics* get() const { return ptr_; }
  InternalMetrics* operator->() const { return ptr_; }
  InternalMetrics& operator*() const { return *ptr_; }

 private:
  NoOpInternalMetrics noop_internal_metrics_;
  InternalMetrics* ptr_;
};

// InternalMetricsPauseWrapper wraps an instance of InternalMetrics, and adds the ability to pause
// logging. This is important to support pausing logging during batch logging to cobalt.
class InternalMetricsPauseWrapper : public InternalMetrics {
 public:
  explicit InternalMetricsPauseWrapper(InternalMetrics* internal_metrics)
      : wrapped_internal_metrics_(internal_metrics), paused_(false) {}

  void LoggerCalled(PerProjectLoggerCallsMadeMetricDimensionLoggerMethod method,
                    const Project& project) override {
    if (!paused_) {
      wrapped_internal_metrics_->LoggerCalled(method, project);
    }
  }

  void BytesUploaded(PerDeviceBytesUploadedMetricDimensionStatus upload_status,
                     int64_t byte_count) override {
    if (!paused_) {
      wrapped_internal_metrics_->BytesUploaded(upload_status, byte_count);
    }
  }

  void BytesUploaded(PerProjectBytesUploadedMetricDimensionStatus upload_status, int64_t byte_count,
                     uint32_t customer_id, uint32_t project_id) override {
    if (!paused_) {
      wrapped_internal_metrics_->BytesUploaded(upload_status, byte_count, customer_id, project_id);
    }
  }

  void BytesStored(PerProjectBytesStoredMetricDimensionStatus upload_status, int64_t byte_count,
                   uint32_t customer_id, uint32_t project_id) override {
    if (!paused_) {
      wrapped_internal_metrics_->BytesStored(upload_status, byte_count, customer_id, project_id);
    }
  }

  void IdleObservationUpload(IdleObservationUploadMetricDimensionDeviceState state) override {
    if (!paused_) {
      wrapped_internal_metrics_->IdleObservationUpload(state);
    }
  }

  void InaccurateClockEventsCached(int64_t event_count, uint32_t customer_id,
                                   uint32_t project_id) override {
    if (!paused_) {
      wrapped_internal_metrics_->InaccurateClockEventsCached(event_count, customer_id, project_id);
    }
  }

  void InaccurateClockEventsDropped(int64_t event_count, uint32_t customer_id,
                                    uint32_t project_id) override {
    if (!paused_) {
      wrapped_internal_metrics_->InaccurateClockEventsDropped(event_count, customer_id, project_id);
    }
  }

  void SetSoftwareDistributionInfoCalled(
      SetSoftwareDistributionInfoCalledEventCodes event_codes) override {
    if (!paused_) {
      wrapped_internal_metrics_->SetSoftwareDistributionInfoCalled(event_codes);
    }
  }

  void TrackDiskUsage(StorageClass storage_class, int64_t bytes, int64_t max_bytes) override {
    if (!paused_) {
      wrapped_internal_metrics_->TrackDiskUsage(storage_class, bytes, max_bytes);
    }
  }

  // After PauseLogging is called, all calls to log internal metrics will be
  // ignored.
  void PauseLogging() { paused_ = true; }

  // Once ResumeLogging is called, calls to log internal metrics are will no
  // longer be ignored.
  void ResumeLogging() { paused_ = false; }

  void Flush() override { wrapped_internal_metrics_->Flush(); }

  [[nodiscard]] bool IsRealImpl() const override { return wrapped_internal_metrics_->IsRealImpl(); }

  void reset(InternalMetrics* internal_metrics) {
    wrapped_internal_metrics_.reset(internal_metrics);
  }

 private:
  InternalMetricsPtr wrapped_internal_metrics_;
  bool paused_;
};

}  // namespace cobalt::logger

#endif  // COBALT_SRC_LOGGER_INTERNAL_METRICS_H_
