// Copyright 2019 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_PUBLIC_COBALT_SERVICE_H_
#define COBALT_SRC_PUBLIC_COBALT_SERVICE_H_

#include <chrono>
#include <cstddef>
#include <memory>
#include <string>

#include "src/lib/util/clock.h"
#include "src/lib/util/consistent_proto_store.h"
#include "src/lib/util/encrypted_message_util.h"
#include "src/local_aggregation/event_aggregator_mgr.h"
#include "src/local_aggregation_1_1/local_aggregation.h"
#include "src/logger/internal_metrics.h"
#include "src/logger/logger.h"
#include "src/logger/observation_writer.h"
#include "src/logger/project_context.h"
#include "src/logger/project_context_factory.h"
#include "src/logger/undated_event_manager.h"
#include "src/observation_store/observation_store.h"
#include "src/pb/metadata_builder.h"
#include "src/public/cobalt_config.h"
#include "src/public/cobalt_service_interface.h"
#include "src/public/lib/http_client.h"
#include "src/system_data/client_secret.h"
#include "src/system_data/system_data.h"
#include "src/uploader/shipping_manager.h"

namespace cobalt {

// CobaltService is the primary public interface for Cobalt on client platforms.
//
// It is constructed using a CobaltConfig struct, which provides all available customization options
// for the behavior of Cobalt.
//
// Example:
//
// CobaltConfig cfg;
// cfg.product_name = "product";
// cfg.version = "version";
// ... continue setting config values ...
//
// CobaltService service(std::move(cfg));
//
// // Get a logger:
//
// auto logger = service.NewLogger(project_context);
// logger.LogEvent(Event);
//
class CobaltService : public CobaltServiceInterface {
 public:
  explicit CobaltService(CobaltConfig cfg);

  // NewLogger returns a new instance of a Logger object based on the provided |project_context|.
  std::unique_ptr<logger::LoggerInterface> NewLogger(
      std::unique_ptr<logger::ProjectContext> project_context) override;

  std::unique_ptr<logger::LoggerInterface> NewLogger(uint32_t customer_id,
                                                     uint32_t project_id) override;

 private:
  std::unique_ptr<logger::Logger> NewLogger(std::unique_ptr<logger::ProjectContext> project_context,
                                            bool include_internal_logger);

  std::unique_ptr<logger::Logger> NewLogger(uint32_t customer_id, uint32_t project_id,
                                            bool include_internal_logger);

 public:
  // SystemClockIsAccurate lets CobaltService know that it no longer needs to maintain an
  // UndatedEventManager, and can flush the data from it into the observation store.
  //
  // This method should be used at most once in the lifetime of a CobaltService object.
  //
  // |system_clock|: An instance of SystemClockInterface that is used to add a timestamp to all of
  // the events that were received before the system clock was made accurate. It is then given to
  // the EventAggregator if |start_event_aggregator_worker| is true.
  void SystemClockIsAccurate(std::unique_ptr<util::SystemClockInterface> system_clock,
                             bool start_event_aggregator_worker) override;

  // system_data returns a pointer to the internal SystemData object. This should only be used for
  // updating the Expirement state or channel in SystemData.
  system_data::SystemDataInterface *system_data() override { return &system_data_; }

  // Sets the data collection policy.
  void SetDataCollectionPolicy(DataCollectionPolicy policy) override;

  logger::Status GenerateAggregatedObservations() override;
  logger::Status GenerateAggregatedObservations(uint32_t final_day_index_utc) override;

  [[nodiscard]] uint64_t num_aggregator_runs() const override {
    return event_aggregator_manager_.num_runs();
  }

  [[nodiscard]] uint64_t num_observations_added() const override {
    return observation_store_->num_observations_added();
  }

  [[nodiscard]] std::vector<uint64_t> num_observations_added_for_reports(
      const std::vector<ReportSpec> &report_specs) const override {
    return observation_store_->num_observations_added_for_reports(report_specs);
  }

  void ShippingRequestSendSoon(const SendCallback &send_callback) override {
    shipping_manager_->RequestSendSoon(send_callback);
  }

  void WaitUntilShippingIdle(std::chrono::seconds max_wait) override {
    shipping_manager_->WaitUntilIdle(max_wait);
  }

  void ShutDown() override { local_aggregation_.ShutDown(); }

  [[nodiscard]] size_t num_shipping_send_attempts() const override {
    return shipping_manager_->num_send_attempts();
  }
  [[nodiscard]] size_t num_shipping_failed_attempts() const override {
    return shipping_manager_->num_failed_attempts();
  }

  bool has_internal_logger() const { return internal_logger_ != nullptr; }

 private:
  friend class internal::RealLoggerFactory;
  friend class CobaltControllerImpl;
  friend class CobaltServiceTest;

  observation_store::ObservationStore *observation_store() { return observation_store_.get(); }

  local_aggregation::EventAggregatorManager *event_aggregator_manager() {
    return &event_aggregator_manager_;
  }

  uploader::ShippingManager *shipping_manager() { return shipping_manager_.get(); }

  const bool enable_replacement_metrics_;

  std::unique_ptr<util::FileSystem> fs_;
  system_data::SystemData system_data_;
  std::unique_ptr<logger::ProjectContextFactory> global_project_context_factory_;
  std::unique_ptr<observation_store::ObservationStore> observation_store_;
  std::unique_ptr<util::EncryptedMessageMaker> encrypt_to_analyzer_;
  std::unique_ptr<util::EncryptedMessageMaker> encrypt_to_shuffler_;
  std::unique_ptr<uploader::ShippingManager> shipping_manager_;
  MetadataBuilder metadata_builder_;
  logger::Encoder logger_encoder_;
  logger::ObservationWriter observation_writer_;
  local_aggregation::EventAggregatorManager event_aggregator_manager_;
  local_aggregation::LocalAggregation local_aggregation_;
  std::shared_ptr<logger::UndatedEventManager> undated_event_manager_;
  util::ValidatedClockInterface *validated_clock_;
  std::unique_ptr<logger::LoggerInterface> internal_logger_;
  std::unique_ptr<logger::InternalMetrics> internal_metrics_;
  std::unique_ptr<util::SystemClockInterface> system_clock_;
  bool start_worker_threads_;
};

}  // namespace cobalt

#endif  // COBALT_SRC_PUBLIC_COBALT_SERVICE_H_
