// Copyright 2017 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 <memory>
#include <string>

#include <lib/async-loop/cpp/loop.h>
#include <lib/async/cpp/task.h>
#include <lib/backoff/exponential_backoff.h>
#include <lib/component/cpp/testing/startup_context_for_test.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fit/function.h>
#include <lib/fsl/handles/object_info.h>
#include <lib/fsl/socket/strings.h>
#include <lib/fxl/files/scoped_temp_dir.h>
#include <lib/timekeeper/test_loop_test_clock.h>

#include "gtest/gtest.h"
#include "peridot/bin/ledger/app/ledger_repository_factory_impl.h"
#include "peridot/bin/ledger/fidl/error_notifier.h"
#include "peridot/bin/ledger/fidl_helpers/bound_interface_set.h"
#include "peridot/bin/ledger/p2p_provider/impl/p2p_provider_impl.h"
#include "peridot/bin/ledger/p2p_sync/impl/user_communicator_impl.h"
#include "peridot/bin/ledger/p2p_sync/public/user_communicator_factory.h"
#include "peridot/bin/ledger/testing/cloud_provider/fake_cloud_provider.h"
#include "peridot/bin/ledger/testing/cloud_provider/types.h"
#include "peridot/bin/ledger/testing/ledger_app_instance_factory.h"
#include "peridot/bin/ledger/testing/loop_controller_test_loop.h"
#include "peridot/bin/ledger/testing/netconnector/netconnector_factory.h"
#include "peridot/bin/ledger/tests/integration/test_utils.h"
#include "peridot/lib/rng/random.h"
#include "peridot/lib/rng/test_random.h"
#include "peridot/lib/socket/socket_pair.h"
#include "peridot/lib/socket/socket_writer.h"

namespace ledger {
namespace {

constexpr fxl::StringView kLedgerName = "AppTests";
constexpr zx::duration kBackoffDuration = zx::msec(5);
const char kUserId[] = "user";

// Implementation of rng::Random that delegates to another instance. This is
// needed because EnvironmentBuilder requires taking ownership of the random
// implementation.
class DelegatedRandom final : public rng::Random {
 public:
  DelegatedRandom(rng::Random* base) : base_(base) {}
  ~DelegatedRandom() override = default;

 private:
  void InternalDraw(void* buffer, size_t buffer_size) {
    base_->Draw(buffer, buffer_size);
  }

  rng::Random* base_;
};

Environment BuildEnvironment(async::TestLoop* loop,
                             async_dispatcher_t* dispatcher,
                             async_dispatcher_t* io_dispatcher,
                             component::StartupContext* startup_context,
                             rng::Random* random) {
  return EnvironmentBuilder()
      .SetAsync(dispatcher)
      .SetIOAsync(io_dispatcher)
      .SetStartupContext(startup_context)
      .SetBackoffFactory([random] {
        return std::make_unique<backoff::ExponentialBackoff>(
            kBackoffDuration, 1u, kBackoffDuration,
            random->NewBitGenerator<uint64_t>());
      })
      .SetClock(std::make_unique<timekeeper::TestLoopTestClock>(loop))
      .SetRandom(std::make_unique<DelegatedRandom>(random))
      .Build();
}

class LedgerAppInstanceImpl final
    : public LedgerAppInstanceFactory::LedgerAppInstance {
 public:
  LedgerAppInstanceImpl(
      LoopControllerTestLoop* loop_controller,
      async_dispatcher_t* services_dispatcher, rng::Random* random,
      fidl::InterfaceRequest<ledger_internal::LedgerRepositoryFactory>
          repository_factory_request,
      fidl::InterfacePtr<ledger_internal::LedgerRepositoryFactory>
          repository_factory_ptr,
      fidl_helpers::BoundInterfaceSet<cloud_provider::CloudProvider,
                                      FakeCloudProvider>* cloud_provider,
      std::unique_ptr<p2p_sync::UserCommunicatorFactory>
          user_communicator_factory);
  ~LedgerAppInstanceImpl() override;

 private:
  class LedgerRepositoryFactoryContainer {
   public:
    LedgerRepositoryFactoryContainer(
        async::TestLoop* loop, async_dispatcher_t* dispatcher,
        async_dispatcher_t* io_dispatcher, rng::Random* random,
        fidl::InterfaceRequest<ledger_internal::LedgerRepositoryFactory>
            request,
        std::unique_ptr<p2p_sync::UserCommunicatorFactory>
            user_communicator_factory)
        : startup_context_(component::testing::StartupContextForTest::Create()),
          environment_(BuildEnvironment(loop, dispatcher, io_dispatcher,
                                        startup_context_.get(), random)),
          factory_impl_(&environment_, std::move(user_communicator_factory),
                        component::ObjectDir()),
          binding_(&factory_impl_, std::move(request)) {}
    ~LedgerRepositoryFactoryContainer() {}

   private:
    std::unique_ptr<component::StartupContext> startup_context_;
    Environment environment_;
    LedgerRepositoryFactoryImpl factory_impl_;
    ErrorNotifierBinding<
        fuchsia::ledger::internal::LedgerRepositoryFactoryErrorNotifierDelegate>
        binding_;

    FXL_DISALLOW_COPY_AND_ASSIGN(LedgerRepositoryFactoryContainer);
  };

  cloud_provider::CloudProviderPtr MakeCloudProvider() override;
  std::string GetUserId() override;

  std::unique_ptr<SubLoop> loop_;
  std::unique_ptr<SubLoop> io_loop_;
  std::unique_ptr<LedgerRepositoryFactoryContainer> factory_container_;
  async_dispatcher_t* services_dispatcher_;
  fidl_helpers::BoundInterfaceSet<cloud_provider::CloudProvider,
                                  FakeCloudProvider>* const cloud_provider_;

  // This must be the last field of this class.
  fxl::WeakPtrFactory<LedgerAppInstanceImpl> weak_ptr_factory_;
};

LedgerAppInstanceImpl::LedgerAppInstanceImpl(
    LoopControllerTestLoop* loop_controller,
    async_dispatcher_t* services_dispatcher, rng::Random* random,
    fidl::InterfaceRequest<ledger_internal::LedgerRepositoryFactory>
        repository_factory_request,
    fidl::InterfacePtr<ledger_internal::LedgerRepositoryFactory>
        repository_factory_ptr,
    fidl_helpers::BoundInterfaceSet<cloud_provider::CloudProvider,
                                    FakeCloudProvider>* cloud_provider,
    std::unique_ptr<p2p_sync::UserCommunicatorFactory>
        user_communicator_factory)
    : LedgerAppInstanceFactory::LedgerAppInstance(
          loop_controller, convert::ToArray(kLedgerName),
          std::move(repository_factory_ptr)),
      loop_(loop_controller->StartNewLoop()),
      io_loop_(loop_controller->StartNewLoop()),
      services_dispatcher_(services_dispatcher),
      cloud_provider_(cloud_provider),
      weak_ptr_factory_(this) {
  async::PostTask(loop_->dispatcher(),
                  [this, loop_controller, random,
                   request = std::move(repository_factory_request),
                   user_communicator_factory =
                       std::move(user_communicator_factory)]() mutable {
                    factory_container_ =
                        std::make_unique<LedgerRepositoryFactoryContainer>(
                            &loop_controller->test_loop(), loop_->dispatcher(),
                            io_loop_->dispatcher(), random, std::move(request),
                            std::move(user_communicator_factory));
                  });
}

cloud_provider::CloudProviderPtr LedgerAppInstanceImpl::MakeCloudProvider() {
  cloud_provider::CloudProviderPtr cloud_provider;
  async::PostTask(services_dispatcher_,
                  callback::MakeScoped(
                      weak_ptr_factory_.GetWeakPtr(),
                      [this, request = cloud_provider.NewRequest()]() mutable {
                        cloud_provider_->AddBinding(std::move(request));
                      }));
  return cloud_provider;
}

std::string LedgerAppInstanceImpl::GetUserId() { return kUserId; }

LedgerAppInstanceImpl::~LedgerAppInstanceImpl() {
  async::PostTask(loop_->dispatcher(), [this] { factory_container_.reset(); });
  loop_->DrainAndQuit();
  loop_.release();
}

class FakeUserCommunicatorFactory : public p2p_sync::UserCommunicatorFactory {
 public:
  FakeUserCommunicatorFactory(async::TestLoop* loop,
                              async_dispatcher_t* services_dispatcher,
                              rng::Random* random,
                              NetConnectorFactory* netconnector_factory,
                              std::string host_name)
      : services_dispatcher_(services_dispatcher),
        startup_context_(component::testing::StartupContextForTest::Create()),
        environment_(BuildEnvironment(loop, services_dispatcher,
                                      services_dispatcher,
                                      startup_context_.get(), random)),
        netconnector_factory_(netconnector_factory),
        host_name_(std::move(host_name)),
        weak_ptr_factory_(this) {}
  ~FakeUserCommunicatorFactory() override {}

  std::unique_ptr<p2p_sync::UserCommunicator> GetUserCommunicator(
      std::unique_ptr<p2p_provider::UserIdProvider> user_id_provider) override {
    fuchsia::netconnector::NetConnectorPtr netconnector;
    async::PostTask(services_dispatcher_,
                    callback::MakeScoped(
                        weak_ptr_factory_.GetWeakPtr(),
                        [this, request = netconnector.NewRequest()]() mutable {
                          netconnector_factory_->AddBinding(host_name_,
                                                            std::move(request));
                        }));
    std::unique_ptr<p2p_provider::P2PProvider> provider =
        std::make_unique<p2p_provider::P2PProviderImpl>(
            host_name_, std::move(netconnector), std::move(user_id_provider));
    return std::make_unique<p2p_sync::UserCommunicatorImpl>(
        std::move(provider), environment_.coroutine_service());
  }

 private:
  async_dispatcher_t* const services_dispatcher_;
  std::unique_ptr<component::StartupContext> startup_context_;
  Environment environment_;
  NetConnectorFactory* const netconnector_factory_;
  std::string host_name_;

  // This must be the last field of this class.
  fxl::WeakPtrFactory<FakeUserCommunicatorFactory> weak_ptr_factory_;
};

enum EnableP2PMesh { NO, YES };

}  // namespace

class LedgerAppInstanceFactoryImpl : public LedgerAppInstanceFactory {
 public:
  LedgerAppInstanceFactoryImpl(InjectNetworkError inject_network_error,
                               EnableP2PMesh enable_p2p_mesh)
      : loop_controller_(&loop_),
        random_(loop_.initial_state()),
        services_loop_(loop_controller_.StartNewLoop()),
        cloud_provider_(FakeCloudProvider::Builder().SetInjectNetworkError(
            inject_network_error)),
        enable_p2p_mesh_(enable_p2p_mesh) {}
  ~LedgerAppInstanceFactoryImpl() override;

  std::unique_ptr<LedgerAppInstance> NewLedgerAppInstance() override;

  LoopController* GetLoopController() override;

  rng::Random* GetRandom() override;

 private:
  async::TestLoop loop_;
  LoopControllerTestLoop loop_controller_;
  rng::TestRandom random_;
  // Loop on which to run services.
  std::unique_ptr<SubLoop> services_loop_;
  fidl_helpers::BoundInterfaceSet<cloud_provider::CloudProvider,
                                  FakeCloudProvider>
      cloud_provider_;
  int app_instance_counter_ = 0;
  NetConnectorFactory netconnector_factory_;
  const EnableP2PMesh enable_p2p_mesh_;
};

LedgerAppInstanceFactoryImpl::~LedgerAppInstanceFactoryImpl() {
  services_loop_->DrainAndQuit();
  services_loop_.reset();
}

std::unique_ptr<LedgerAppInstanceFactory::LedgerAppInstance>
LedgerAppInstanceFactoryImpl::NewLedgerAppInstance() {
  ledger_internal::LedgerRepositoryFactoryPtr repository_factory_ptr;
  fidl::InterfaceRequest<ledger_internal::LedgerRepositoryFactory>
      repository_factory_request = repository_factory_ptr.NewRequest();

  std::unique_ptr<p2p_sync::UserCommunicatorFactory> user_communicator_factory;
  if (enable_p2p_mesh_ == EnableP2PMesh::YES) {
    std::string host_name = "host_" + std::to_string(app_instance_counter_);
    user_communicator_factory = std::make_unique<FakeUserCommunicatorFactory>(
        &loop_controller_.test_loop(), services_loop_->dispatcher(), &random_,
        &netconnector_factory_, std::move(host_name));
  }
  auto result = std::make_unique<LedgerAppInstanceImpl>(
      &loop_controller_, services_loop_->dispatcher(), &random_,
      std::move(repository_factory_request), std::move(repository_factory_ptr),
      &cloud_provider_, std::move(user_communicator_factory));
  app_instance_counter_++;
  return result;
}

LoopController* LedgerAppInstanceFactoryImpl::GetLoopController() {
  return &loop_controller_;
}

rng::Random* LedgerAppInstanceFactoryImpl::GetRandom() { return &random_; }

namespace {

class FactoryBuilderIntegrationImpl : public LedgerAppInstanceFactoryBuilder {
 public:
  FactoryBuilderIntegrationImpl(InjectNetworkError inject_error,
                                EnableP2PMesh enable_p2p)
      : inject_error_(inject_error), enable_p2p_(enable_p2p){};

  std::unique_ptr<LedgerAppInstanceFactory> NewFactory() const override {
    return std::make_unique<LedgerAppInstanceFactoryImpl>(inject_error_,
                                                          enable_p2p_);
  }

 private:
  InjectNetworkError inject_error_;
  EnableP2PMesh enable_p2p_;
};

}  // namespace

std::vector<const LedgerAppInstanceFactoryBuilder*>
GetLedgerAppInstanceFactoryBuilders() {
  static std::vector<std::unique_ptr<FactoryBuilderIntegrationImpl>>
      static_builders;
  static std::once_flag flag;

  auto static_builders_ptr = &static_builders;
  std::call_once(flag, [&static_builders_ptr] {
    for (auto inject_error :
         {InjectNetworkError::NO, InjectNetworkError::YES}) {
      for (auto enable_p2p : {EnableP2PMesh::NO, EnableP2PMesh::YES}) {
        if (enable_p2p == EnableP2PMesh::YES &&
            inject_error != InjectNetworkError::YES) {
          // Only enable p2p when cloud has errors. This helps ensure our tests
          // are fast enough for the CQ.
          continue;
        }
        static_builders_ptr->push_back(
            std::make_unique<FactoryBuilderIntegrationImpl>(inject_error,
                                                            enable_p2p));
      }
    }
  });

  std::vector<const LedgerAppInstanceFactoryBuilder*> builders;

  for (const auto& builder : static_builders) {
    builders.push_back(builder.get());
  }

  return builders;
}

}  // namespace ledger
