// Copyright 2016 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 "peridot/bin/ledger/environment/environment.h"

#include <lib/backoff/exponential_backoff.h>
#include <lib/fxl/macros.h>
#include <lib/timekeeper/system_clock.h>

#include "peridot/bin/ledger/coroutine/coroutine_impl.h"
#include "peridot/lib/ledger_client/constants.h"
#include "peridot/lib/rng/system_random.h"

namespace ledger {

Environment::Environment(
    bool disable_statistics, async_dispatcher_t* dispatcher,
    async_dispatcher_t* io_dispatcher, std::string firebase_api_key,
    component::StartupContext* startup_context,
    std::unique_ptr<coroutine::CoroutineService> coroutine_service,
    BackoffFactory backoff_factory, std::unique_ptr<timekeeper::Clock> clock,
    std::unique_ptr<rng::Random> random)
    : disable_statistics_(disable_statistics),
      dispatcher_(dispatcher),
      io_dispatcher_(io_dispatcher),
      firebase_api_key_(std::move(firebase_api_key)),
      startup_context_(startup_context),
      coroutine_service_(std::move(coroutine_service)),
      backoff_factory_(std::move(backoff_factory)),
      clock_(std::move(clock)),
      random_(std::move(random)) {
  FXL_DCHECK(dispatcher_);
  FXL_DCHECK(io_dispatcher_);
  FXL_DCHECK(startup_context_);
  FXL_DCHECK(coroutine_service_);
  FXL_DCHECK(backoff_factory_);
  FXL_DCHECK(clock_);
  FXL_DCHECK(random_);
}

Environment::Environment(Environment&& other) noexcept {
  *this = std::move(other);
}

Environment& Environment::operator=(Environment&& other) noexcept {
  disable_statistics_ = other.disable_statistics_;
  dispatcher_ = other.dispatcher_;
  io_dispatcher_ = other.io_dispatcher_;
  firebase_api_key_ = std::move(other.firebase_api_key_);
  startup_context_ = other.startup_context_;
  coroutine_service_ = std::move(other.coroutine_service_);
  backoff_factory_ = std::move(other.backoff_factory_);
  clock_ = std::move(other.clock_);
  random_ = std::move(other.random_);
  FXL_DCHECK(dispatcher_);
  FXL_DCHECK(io_dispatcher_);
  FXL_DCHECK(startup_context_);
  FXL_DCHECK(coroutine_service_);
  FXL_DCHECK(backoff_factory_);
  FXL_DCHECK(clock_);
  FXL_DCHECK(random_);
  return *this;
}

Environment::~Environment() {}

std::unique_ptr<backoff::Backoff> Environment::MakeBackoff() {
  return backoff_factory_();
}

EnvironmentBuilder::EnvironmentBuilder()
    : firebase_api_key_(modular::kFirebaseApiKey) {}

EnvironmentBuilder::~EnvironmentBuilder() {}

EnvironmentBuilder& EnvironmentBuilder::SetDisableStatistics(
    bool disable_statistics) {
  disable_statistics_ = disable_statistics;
  return *this;
}

EnvironmentBuilder& EnvironmentBuilder::SetAsync(
    async_dispatcher_t* dispatcher) {
  dispatcher_ = dispatcher;
  return *this;
}

EnvironmentBuilder& EnvironmentBuilder::SetIOAsync(
    async_dispatcher_t* io_dispatcher) {
  io_dispatcher_ = io_dispatcher;
  return *this;
}

EnvironmentBuilder& EnvironmentBuilder::SetFirebaseApiKey(
    std::string firebase_api_key) {
  firebase_api_key_ = std::move(firebase_api_key);
  return *this;
}

EnvironmentBuilder& EnvironmentBuilder::SetStartupContext(
    component::StartupContext* startup_context) {
  startup_context_ = startup_context;
  return *this;
}

EnvironmentBuilder& EnvironmentBuilder::SetCoroutineService(
    std::unique_ptr<coroutine::CoroutineService> coroutine_service) {
  coroutine_service_ = std::move(coroutine_service);
  return *this;
}

// public
EnvironmentBuilder& EnvironmentBuilder::SetBackoffFactory(
    Environment::BackoffFactory backoff_factory) {
  backoff_factory_ = std::move(backoff_factory);
  return *this;
}

EnvironmentBuilder& EnvironmentBuilder::SetClock(
    std::unique_ptr<timekeeper::Clock> clock) {
  clock_ = std::move(clock);
  return *this;
}

EnvironmentBuilder& EnvironmentBuilder::SetRandom(
    std::unique_ptr<rng::Random> random) {
  random_ = std::move(random);
  return *this;
}

Environment EnvironmentBuilder::Build() {
  if (!coroutine_service_) {
    coroutine_service_ = std::make_unique<coroutine::CoroutineServiceImpl>();
  }
  if (!clock_) {
    clock_ = std::make_unique<timekeeper::SystemClock>();
  }
  if (!random_) {
    random_ = std::make_unique<rng::SystemRandom>();
  }
  if (!backoff_factory_) {
    backoff_factory_ = [random = random_.get()] {
      return std::make_unique<backoff::ExponentialBackoff>(
          random->NewBitGenerator<uint64_t>());
    };
  }
  return Environment(disable_statistics_, dispatcher_, io_dispatcher_,
                     std::move(firebase_api_key_), startup_context_,
                     std::move(coroutine_service_), std::move(backoff_factory_),
                     std::move(clock_), std::move(random_));
}

}  // namespace ledger
