// Copyright 2020 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_LOCAL_AGGREGATION_1_1_LOCAL_AGGREGATE_STORAGE_LOCAL_AGGREGATE_STORAGE_H_
#define COBALT_SRC_LOCAL_AGGREGATION_1_1_LOCAL_AGGREGATE_STORAGE_LOCAL_AGGREGATE_STORAGE_H_

#include <mutex>

#include "src/lib/statusor/statusor.h"
#include "src/lib/util/file_system.h"
#include "src/lib/util/status.h"
#include "src/local_aggregation_1_1/local_aggregation.pb.h"
#include "src/logger/logger_interface.h"
#include "src/logger/project_context_factory.h"

namespace cobalt::local_aggregation {

// LocalAggregateStorage is the generic interface for storing MetricAggregates.
//
// Different systems perform better with different implementations of this class, so it is up to the
// embedder to chose which StorageStrategy is best.
class LocalAggregateStorage {
 public:
  enum class StorageStrategy {
    // Use the ImmediateLocalAggregateStorage implementation. This method writes to disk
    // synchronously after each call to SaveMetricAggregate.
    Immediate,

    // Use the DelayedLocalAggregateStorage implementation. This method is best used on embeddings
    // where writes to disk are slow, or write amplification is an issue.
    Delayed,
  };

  // MetricAggregateRef contains a pointer to the requested MetricAggregate, as well as unique_lock
  // that holds the mutex for the LocalAggregateStorage it came from.
  class MetricAggregateRef {
   public:
    MetricAggregateRef(uint32_t customer_id, uint32_t project_id, uint32_t metric_id,
                       MetricAggregate *aggregate, LocalAggregateStorage *self, std::mutex &mutex)
        : customer_id_(customer_id),
          project_id_(project_id),
          metric_id_(metric_id),
          aggregate_(aggregate),
          self_(self),
          lock_(mutex) {}

    MetricAggregateRef(uint32_t customer_id, uint32_t project_id, uint32_t metric_id,
                       MetricAggregate *aggregate, LocalAggregateStorage *self,
                       std::unique_lock<std::mutex> mutex_lock)
        : customer_id_(customer_id),
          project_id_(project_id),
          metric_id_(metric_id),
          aggregate_(aggregate),
          self_(self),
          lock_(std::move(mutex_lock)) {}

    // Returns the pointer to the contained MetricAggregate
    MetricAggregate *aggregate() { return aggregate_; }

    // Triggers the source LocalAggregateStorage to save the given MetricAggregate.
    util::Status Save() {
      return self_->SaveMetricAggregate(customer_id_, project_id_, metric_id_);
    }

   private:
    uint32_t customer_id_;
    uint32_t project_id_;
    uint32_t metric_id_;

    MetricAggregate *aggregate_;
    LocalAggregateStorage *self_;
    std::unique_lock<std::mutex> lock_;
  };

  // New is the expected way to construct LocalAggregateStorage objects. Depending on which
  // StorageStrategy is supplied, a different implementation of LocalAggregateStorage will be used.
  static std::unique_ptr<LocalAggregateStorage> New(
      StorageStrategy strategy, std::string base_directory, util::FileSystem *fs,
      const logger::ProjectContextFactory *global_project_context_factory);

  // GetMetricAggregate returns a pointer to the live, mutable MetricAggregate that was requested.
  // If no such aggregate exists, nullptr will be returned.
  //
  // Note: After modifying the MetricAggregate returned by this function, the user is expected to
  // call 'SaveMetricAggregate' so that the modified values can be persisted to disk.
  virtual lib::statusor::StatusOr<MetricAggregateRef> GetMetricAggregate(uint32_t customer_id,
                                                                         uint32_t project_id,
                                                                         uint32_t metric_id) = 0;

  // When DeleteData is called, all aggregated data should be deleted and written to disk
  // immediately.
  virtual void DeleteData() = 0;

  virtual void ResetInternalMetrics(logger::LoggerInterface *internal_logger) = 0;

  virtual ~LocalAggregateStorage() = default;

 protected:
  // SaveMetricAggregate writes the current state of the MetricAggregate for the given
  // (customer, project, metric) tuple to disk.
  //
  // Note: This should be called after modifying the MetricAggregate returned by GetMetricAggregate.
  virtual util::Status SaveMetricAggregate(uint32_t customer_id, uint32_t project_id,
                                           uint32_t metric_id) = 0;
};

}  // namespace cobalt::local_aggregation

#endif  // COBALT_SRC_LOCAL_AGGREGATION_1_1_LOCAL_AGGREGATE_STORAGE_LOCAL_AGGREGATE_STORAGE_H_
