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

#include "src/local_aggregation_1_1/local_aggregation.h"

#include <algorithm>
#include <memory>

#include "src/lib/util/clock.h"
#include "src/lib/util/datetime_util.h"
#include "src/lib/util/hash.h"
#include "src/local_aggregation_1_1/aggregation_procedures/aggregation_procedure.h"
#include "src/local_aggregation_1_1/local_aggregate_storage/local_aggregate_storage.h"
#include "src/logger/privacy_encoder.h"
#include "src/logger/project_context_factory.h"
#include "src/pb/metadata_builder.h"
#include "src/pb/observation_batch.pb.h"
#include "src/public/lib/registry_identifiers.h"
#include "src/public/lib/statusor/status_macros.h"
#include "src/registry/report_definition.pb.h"
#include "src/system_data/system_data.h"

namespace cobalt::local_aggregation {

LocalAggregation::LocalAggregation(
    const CobaltConfig &cfg, const logger::ProjectContextFactory *global_project_context_factory,
    system_data::SystemDataInterface *system_data, MetadataBuilder &metadata_builder,
    util::FileSystem &fs, const logger::ObservationWriter &observation_writer,
    util::CivilTimeConverterInterface *civil_time_converter)
    : global_project_context_factory_(global_project_context_factory),
      aggregate_storage_(LocalAggregateStorage::New(
          cfg.local_aggregate_store_strategy, cfg.local_aggregate_store_dir, fs,
          global_project_context_factory, metadata_builder,
          cfg.storage_quotas.per_project_reserved_bytes)),
      observation_generator_(*aggregate_storage_, global_project_context_factory, system_data,
                             observation_writer, logger::PrivacyEncoder::MakeSecurePrivacyEncoder(),
                             civil_time_converter,
                             cfg.generate_observations_with_current_system_profile,
                             cfg.local_aggregation_backfill_days + 1),
      storage_quotas_(cfg.storage_quotas) {
  CHECK(SlushSize() > 0)
      << "There is no space in slush! The number of cobalt customers * per_project_reserved_bytes "
         "is greater than total_capacity_bytes. Please reduce per_project_reserved_bytes or "
         "increase total_capacity_bytes.";
}

int64_t LocalAggregation::SlushUsed() const { return aggregate_storage_->SlushUsed(); }

int64_t LocalAggregation::SlushSize() const {
  return storage_quotas_.total_capacity_bytes -
         (storage_quotas_.per_project_reserved_bytes *
          static_cast<int64_t>(global_project_context_factory_->ListProjects().size()));
}

bool LocalAggregation::CanStore(lib::ProjectIdentifier project) const {
  size_t project_used = aggregate_storage_->AmountStored(project);
  if (project_used < storage_quotas_.per_project_reserved_bytes) {
    return true;
  }
  return SlushUsed() < SlushSize();
}

Status LocalAggregation::AddEvent(const logger::EventRecord &event_record,
                                  const std::chrono::system_clock::time_point &event_timestamp) {
  if (IsDisabled()) {
    return Status::OkStatus();
  }

  lib::ProjectIdentifier proj = event_record.project_context()->Identifier();
  if (!CanStore(proj)) {
    return util::StatusBuilder(StatusCode::RESOURCE_EXHAUSTED,
                               "There is not enough space to add event: ")
        .AppendMsg(event_record)
        .WithContext("project_bytes", aggregate_storage_->AmountStored(proj))
        .WithContext("per_project_reserved_bytes", storage_quotas_.per_project_reserved_bytes)
        .WithContext("SlushUsed", SlushUsed())
        .WithContext("SlushSize", SlushSize())
        .Build();
  }

  CB_ASSIGN_OR_RETURN(LocalAggregateStorage::MetricAggregateRef aggregate,
                      aggregate_storage_->GetMetricAggregate(event_record.MetricIdentifier()));

  // Get the unfiltered global system profile to log with this event.
  const SystemProfile &unfiltered_system_profile = *event_record.system_profile();

  for (const auto &report : event_record.metric()->reports()) {
    CB_ASSIGN_OR_RETURN(std::unique_ptr<AggregationProcedure> procedure,
                        AggregationProcedure::Get(*event_record.metric(), report));
    if (procedure) {
      google::protobuf::Map<uint32_t, ReportAggregate> *by_report_id =
          aggregate.aggregate()->mutable_by_report_id();
      ReportAggregate &report_aggregate = (*by_report_id)[report.id()];

      // Get the filtered global system profile for this report.
      SystemProfile filtered_system_profile;
      MetadataBuilder::FilteredSystemProfile(report, unfiltered_system_profile,
                                             &filtered_system_profile);

      // Calculate the hash of the final filtered system profile.
      uint64_t system_profile_hash = util::Farmhash64(filtered_system_profile.SerializeAsString());

      procedure->UpdateAggregate(event_record, report_aggregate, system_profile_hash,
                                 event_timestamp);

      // Make sure the final filtered system profile is stored.
      aggregate.StoreFilteredSystemProfile(system_profile_hash, filtered_system_profile);
    }
  }

  return aggregate.Save();
}

void LocalAggregation::Start(std::unique_ptr<util::SystemClockInterface> clock) {
  system_clock_ = std::move(clock);
  observation_generator_.Start(system_clock_.get());
}

void LocalAggregation::ShutDown() {
  observation_generator_.ShutDown();
  aggregate_storage_->ShutDown();
}

Status LocalAggregation::GenerateAggregatedObservations(
    std::chrono::system_clock::time_point system_time) {
  return observation_generator_.GenerateObservationsOnce(system_time);
}

void LocalAggregation::Disable(bool is_disabled) {
  LOG(INFO) << "LocalAggregation: " << (is_disabled ? "Disabling" : "Enabling")
            << " local aggregation.";
  is_disabled_ = is_disabled;
}

}  // namespace cobalt::local_aggregation
