// 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_LOGGER_TEST_UTILS_H_
#define COBALT_SRC_LOGGER_LOGGER_TEST_UTILS_H_

#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "src/lib/util/consistent_proto_store.h"
#include "src/lib/util/posix_file_system.h"
#include "src/logger/project_context.h"
#include "src/logger/project_context_factory.h"
#include "src/observation_store/observation_store.h"
#include "src/observation_store/observation_store_update_recipient.h"
#include "src/public/lib/status.h"

namespace cobalt::logger::testing {

// A representation of a set of expected ReportParticipationObservations. Used
// to check the values of ReportParticipationObservations generated by the
// EventAggregator. The first element of each pair is the MetricReportId of a
// report, and the second element represents the day index of an expected
// Observation for that report. a pair is a a set of window sizes.
using ExpectedReportParticipationObservations = std::set<std::pair<MetricReportId, uint32_t>>;

// A mock ObservationStore.
// TODO(https://fxbug.dev/278925674): Move this to a more appropriate location (Perhaps in
// src/observation_store)
class FakeObservationStore : public ::cobalt::observation_store::ObservationStoreWriterInterface {
 public:
  using ::cobalt::observation_store::ObservationStoreWriterInterface::StoreObservation;

  Status StoreObservation(std::unique_ptr<::cobalt::observation_store::StoredObservation> message,
                          std::unique_ptr<ObservationMetadata> metadata) override {
    if (fail_calls_) {
      return ::cobalt::Status(StatusCode::FAILED_PRECONDITION, "fail_calls was set");
    }
    messages_received.emplace_back(std::move(message));
    metadata_received.emplace_back(std::move(metadata));
    num_observations_added_++;
    return Status::OkStatus();
  }

  std::vector<std::unique_ptr<::cobalt::observation_store::StoredObservation>>
      messages_received;                                                // NOLINT
  std::vector<std::unique_ptr<ObservationMetadata>> metadata_received;  // NOLINT

  size_t num_observations_added() const { return num_observations_added_; }

  void ResetObservationCounter() { num_observations_added_ = 0; }

  void SetFailCalls(bool fail_calls) { fail_calls_ = fail_calls; }

 private:
  size_t num_observations_added_ = 0;
  bool fail_calls_ = false;
};

// A mock ObservationStoreUpdateRecipient.
class TestUpdateRecipient : public ::cobalt::observation_store::ObservationStoreUpdateRecipient {
 public:
  void NotifyObservationsAdded() override { invocation_count++; }

  int invocation_count = 0;
};

// A mock ConsistentProtoStore. Its Read() and Write() methods increment
// counts of their invocations.
class MockConsistentProtoStore : public ::cobalt::util::ConsistentProtoStore {
 public:
  explicit MockConsistentProtoStore(std::string filename)
      : ::cobalt::util::ConsistentProtoStore(std::move(filename), fs_) {
    read_count_ = 0;
    write_count_ = 0;
  }

  ~MockConsistentProtoStore() override = default;

  // To set the stored proto in a test, use |set_stored_proto| instead of Write.
  Status Write(const google::protobuf::MessageLite& /*proto*/) override {
    write_count_++;
    return Status::OkStatus();
  }

  Status Read(google::protobuf::MessageLite* proto) override {
    if (stored_proto_) {
      proto->Clear();
      proto->CheckTypeAndMergeFrom(*stored_proto_);
    }
    read_count_++;
    return Status::OkStatus();
  }

  void ResetCounts() {
    read_count_ = 0;
    write_count_ = 0;
  }

  int read_count_;   // NOLINT
  int write_count_;  // NOLINT

  void set_stored_proto(std::unique_ptr<google::protobuf::MessageLite> proto) {
    stored_proto_ = std::move(proto);
  }

 private:
  ::cobalt::util::PosixFileSystem fs_;
  std::unique_ptr<google::protobuf::MessageLite> stored_proto_;
};

// Creates and returns a ProjectContextFactory from a serialized, base64-encoded Cobalt
// registry.
std::unique_ptr<ProjectContextFactory> GetTestProjectContextFactory(
    const std::string& registry_base64);

// Creates and returns a ProjectContext from a serialized, base64-encoded Cobalt
// registry.
std::unique_ptr<ProjectContext> GetTestProject(const std::string& registry_base64);

// Construct a histogram to log from the indices for buckets, and the counts in that bucket.
HistogramPtr NewHistogram(std::vector<uint32_t> indices, std::vector<uint32_t> counts);

// Populates |observations| with the contents of a FakeObservationStore.
// |observations| should be a vector whose size is equal to the number
// of expected observations. Checks the the ObservationStore contains
// the expected number of Observations and that the report_ids of the
// Observations are equal to |expected_report_ids|. Returns true iff all checks
// pass.
bool FetchObservations(std::vector<Observation>* observations,
                       const std::vector<uint32_t>& expected_report_ids,
                       FakeObservationStore& observation_store,
                       TestUpdateRecipient* update_recipient);

// Populates |observation| with the contents of a FakeObservationStore,
// which is expected to contain a single Observation with a report_id
// of |expected_report_id|. Returns true iff all checks pass.
bool FetchSingleObservation(Observation* observation, uint32_t expected_report_id,
                            FakeObservationStore& observation_store,
                            TestUpdateRecipient* update_recipient);

// Checks that the contents of a FakeObservationStore is a sequence of
// IntegerEventObservations specified by the various parameters. Returns
// true if all checks pass.
bool CheckNumericEventObservations(const std::vector<uint32_t>& expected_report_ids,
                                   uint32_t expected_event_code,
                                   const std::string& expected_component_name,
                                   int64_t expected_int_value,
                                   FakeObservationStore& observation_store,
                                   TestUpdateRecipient* update_recipient);

}  // namespace cobalt::logger::testing

#endif  // COBALT_SRC_LOGGER_LOGGER_TEST_UTILS_H_
