// 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/public/diagnostics_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.
  //
  // |diagnostics|: The implementation to send diagnostic information about the
  // functioning of the Cobalt Core library. If null, no diagnostic information
  // will be sent.
  static std::unique_ptr<InternalMetrics> NewWithLogger(LoggerInterface* logger,
                                                        DiagnosticsInterface* diagnostics);

  // 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,
                             size_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,
                             size_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,
                           size_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, size_t bytes, int64_t max_bytes) = 0;
  void TrackDiskUsage(StorageClass storage_class, size_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,
                     size_t byte_count) override {}

  // TODO(fxbug.dev/85571): NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
  void BytesUploaded(PerProjectBytesUploadedMetricDimensionStatus upload_status, size_t byte_count,
                     uint32_t customer_id, uint32_t project_id) override {}

  // TODO(fxbug.dev/85571): NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
  void BytesStored(PerProjectBytesStoredMetricDimensionStatus upload_status, size_t byte_count,
                   uint32_t customer_id, uint32_t project_id) override {}

  void IdleObservationUpload(IdleObservationUploadMetricDimensionDeviceState state) override {}

  // TODO(fxbug.dev/85571): NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
  void InaccurateClockEventsCached(int64_t event_count, uint32_t customer_id,
                                   uint32_t project_id) override {}

  // TODO(fxbug.dev/85571): NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
  void InaccurateClockEventsDropped(int64_t event_count, uint32_t customer_id,
                                    uint32_t project_id) override {}

  void SetSoftwareDistributionInfoCalled(
      SetSoftwareDistributionInfoCalledEventCodes event_codes) override {}

  // TODO(fxbug.dev/85571): NOLINTNEXTLINE(bugprone-easily-swappable-parameters)
  void TrackDiskUsage(StorageClass storage_class, size_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:
  InternalMetricsImpl(LoggerInterface* logger, DiagnosticsInterface* diagnostics);

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

  void BytesUploaded(PerDeviceBytesUploadedMetricDimensionStatus upload_status,
                     size_t byte_count) override;

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

  void BytesStored(PerProjectBytesStoredMetricDimensionStatus upload_status, size_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, size_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
  DiagnosticsInterface* diagnostics_;  // 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) {}

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

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

  void BytesUploaded(PerProjectBytesUploadedMetricDimensionStatus upload_status, size_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, size_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, size_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_ = false;
};

}  // namespace cobalt::logger

#endif  // COBALT_SRC_LOGGER_INTERNAL_METRICS_H_
