// 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.
//
// This application is intenteded to be used for manual testing of
// the Cobalt logger client on Fuchsia by Cobalt engineers.
//
// It also serves as an example of how to use the Cobalt FIDL API.
//
// It is also invoked by the cobalt_client CQ and CI.

#include "src/cobalt/bin/testapp/cobalt_testapp.h"

#include <fuchsia/cobalt/cpp/fidl.h>
#include <fuchsia/component/cpp/fidl.h>
#include <fuchsia/metrics/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/fidl/cpp/synchronous_interface_ptr.h>
#include <lib/sys/component/cpp/testing/realm_builder.h>
#include <lib/sys/component/cpp/testing/scoped_child.h>
#include <lib/sys/cpp/component_context.h>
#include <lib/syslog/cpp/macros.h>

#include <memory>
#include <sstream>
#include <string>
#include <thread>

#include "src/cobalt/bin/testapp/cobalt_testapp_logger.h"
#include "src/cobalt/bin/testapp/prober_metrics_registry.cb.h"
#include "src/cobalt/bin/testapp/testapp_metrics_registry.cb.h"
#include "src/cobalt/bin/testapp/tests.h"

namespace cobalt::testapp {

constexpr char kCobaltWithEventAggregatorWorker[] = "#meta/cobalt_with_event_aggregator_worker.cm";
constexpr char kCobaltNoEventAggregatorWorker[] = "#meta/cobalt_no_event_aggregator_worker.cm";

constexpr uint32_t kControlId = 48954961;
constexpr uint32_t kExperimentId = 48954962;

bool CobaltTestApp::RunTests() {
  { component_testing::ScopedChild child = Connect(kCobaltWithEventAggregatorWorker); }

  return DoLocalAggregationTests(kEventAggregatorBackfillDays, kCobaltNoEventAggregatorWorker);
}

bool CobaltTestApp::DoLocalAggregationTests(const size_t backfill_days,
                                            const std::string &variant) {
  const uint32_t project_id =
      (test_for_prober_ ? cobalt_prober_registry::kProjectId : cobalt_registry::kProjectId);

  constexpr std::array fns = {
      TestLogInteger,
      TestLogIntegerHistogram,
      TestLogOccurrence,
      TestLogString,
  };

  // TODO(b/278930366): We try each of these tests twice in case the failure
  // reason is that the calendar date has changed mid-test.
  for (size_t i = 0; i < 2; ++i) {
    if (std::all_of(fns.begin(), fns.end(), [&](auto fn) {
          // Each function expects to run against a fresh instance.
          component_testing::ScopedChild child = Connect(variant);
          return fn(&logger_, clock_.get(), &cobalt_controller_, backfill_days, project_id);
        })) {
      return true;
    }
  }
  return false;
}

component_testing::ScopedChild CobaltTestApp::Connect(const std::string &variant) {
  fuchsia::component::RealmSyncPtr realm_proxy;
  FX_CHECK(ZX_OK == context_->svc()->Connect(realm_proxy.NewRequest()))
      << "Failed to connect to fuchsia.component.Realm";

  auto child = component_testing::ScopedChild::New(
      std::move(realm_proxy), "realm_builder",
      "cobalt_under_test_" + std::to_string(scoped_children_), variant);
  logger_.SetCobaltUnderTestMoniker("realm_builder\\:" + child.GetChildName());
  scoped_children_ += 1;

  uint32_t project_id =
      (test_for_prober_ ? cobalt_prober_registry::kProjectId : cobalt_registry::kProjectId);
  FX_LOGS(INFO) << "Test app is logging for the " << project_id << " project";
  fuchsia::metrics::MetricEventLoggerFactorySyncPtr metric_event_logger_factory =
      child.ConnectSync<fuchsia::metrics::MetricEventLoggerFactory>();

  fuchsia::metrics::MetricEventLoggerFactory_CreateMetricEventLogger_Result result;
  fuchsia::metrics::ProjectSpec project;
  project.set_customer_id(1);
  project.set_project_id(project_id);
  zx_status_t fx_status = metric_event_logger_factory->CreateMetricEventLogger(
      std::move(project), logger_.metric_event_logger_.NewRequest(), &result);
  FX_CHECK(fx_status == ZX_OK) << "FIDL: CreateMetricEventLogger() => " << fx_status;
  FX_CHECK(!result.is_err()) << "CreateMetricEventLogger() => " << ErrorToString(result.err());

  {
    fuchsia::metrics::MetricEventLoggerFactory_CreateMetricEventLoggerWithExperiments_Result
        result_with_experiments;
    fx_status = metric_event_logger_factory->CreateMetricEventLoggerWithExperiments(
        std::move(project), {kControlId}, logger_.control_metric_event_logger_.NewRequest(),
        &result_with_experiments);
    FX_CHECK(fx_status == ZX_OK) << "FIDL: CreateMetricEventLogger() => " << fx_status;
    FX_CHECK(!result_with_experiments.is_err()) << "CreateMetricEventLoggerWithExperiments() => "
                                                << ErrorToString(result_with_experiments.err());
  }
  {
    fuchsia::metrics::MetricEventLoggerFactory_CreateMetricEventLoggerWithExperiments_Result
        result_with_experiments;
    fx_status = metric_event_logger_factory->CreateMetricEventLoggerWithExperiments(
        std::move(project), {kExperimentId}, logger_.experimental_metric_event_logger_.NewRequest(),
        &result_with_experiments);
    FX_CHECK(fx_status == ZX_OK) << "FIDL: CreateMetricEventLogger() => " << fx_status;
    FX_CHECK(!result_with_experiments.is_err()) << "CreateMetricEventLoggerWithExperiments() => "
                                                << ErrorToString(result_with_experiments.err());
  }

  child.Connect(system_data_updater_.NewRequest());
  fuchsia::cobalt::Status status = fuchsia::cobalt::Status::INTERNAL_ERROR;
  fuchsia::cobalt::SoftwareDistributionInfo info;
  info.set_current_channel("devhost");
  system_data_updater_->SetSoftwareDistributionInfo(std::move(info), &status);
  FX_CHECK(status == fuchsia::cobalt::Status::OK) << "Unable to set software distribution info";

  cobalt_controller_ = child.ConnectSync<fuchsia::cobalt::Controller>();

  // Block until the Cobalt service has been fully initialized. This includes
  // being notified by the timekeeper service that the system clock is accurate.
  FX_LOGS(INFO) << "Blocking until the Cobalt service is fully initialized.";
  cobalt_controller_->ListenForInitialized();
  FX_LOGS(INFO) << "Continuing because the Cobalt service is fully initialzied.";
  return child;
}

}  // namespace cobalt::testapp
