// 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 SRC_CONNECTIVITY_NETWORK_TESTING_NETEMUL_RUNNER_SANDBOX_H_
#define SRC_CONNECTIVITY_NETWORK_TESTING_NETEMUL_RUNNER_SANDBOX_H_

#include <fuchsia/sys/cpp/fidl.h>
#include <fuchsia/virtualization/cpp/fidl.h>
#include <lib/async-loop/cpp/loop.h>
#include <lib/async-loop/default.h>
#include <lib/async/cpp/executor.h>
#include <lib/fit/promise.h>

#include <unordered_set>

#include <src/connectivity/network/testing/netemul/lib/network/netdump.h>

#include "managed_environment.h"
#include "model/config.h"
#include "model/guest.h"
#include "sandbox_env.h"

namespace netemul {

class SandboxArgs {
 public:
  bool ParseFromCmxFileAt(int dir, const std::string& path);
  bool ParseFromString(const std::string& config);
  bool ParseFromJSON(const rapidjson::Value& facet, json::JSONParser* json_parser);

  config::Config config;
};

class SandboxResult {
 public:
  enum Status {
    SUCCESS,
    NETWORK_CONFIG_FAILED,
    SERVICE_EXITED,
    ENVIRONMENT_CONFIG_FAILED,
    TEST_FAILED,
    SETUP_FAILED,
    COMPONENT_FAILURE,
    EMPTY_TEST_SET,
    TIMEOUT,
    INTERNAL_ERROR,
    UNSPECIFIED
  };

  SandboxResult() : status_(SUCCESS) {}
  explicit SandboxResult(Status status) : status_(status) {}

  SandboxResult(Status status, std::string description)
      : status_(status), description_(std::move(description)) {}

  bool is_success() const { return status_ == Status::SUCCESS; }

  Status status() const { return status_; }

  const std::string& description() const { return description_; }

  friend std::ostream& operator<<(std::ostream& os, const SandboxResult& result);

 private:
  Status status_;
  std::string description_;
};

class Sandbox {
 public:
  using TerminationReason = fuchsia::sys::TerminationReason;
  using TerminationCallback = fit::function<void(SandboxResult)>;
  using ServicesCreatedCallback = fit::function<void()>;
  using RootEnvironmentCreatedCallback = fit::function<void(ManagedEnvironment*)>;
  explicit Sandbox(SandboxArgs args);
  ~Sandbox();

  void SetTerminationCallback(TerminationCallback callback) {
    termination_callback_ = std::move(callback);
  }

  void Start(async_dispatcher_t* dispatcher);

  void SetServicesCreatedCallback(ServicesCreatedCallback callback) {
    services_created_callback_ = std::move(callback);
  }

  void SetRootEnvironmentCreatedCallback(RootEnvironmentCreatedCallback callback) {
    root_environment_created_callback_ = std::move(callback);
  }

  const SandboxEnv::Ptr& sandbox_environment() { return sandbox_env_; }

 private:
  using ConfiguringEnvironmentPtr =
      std::shared_ptr<fidl::SynchronousInterfacePtr<ManagedEnvironment::FManagedEnvironment>>;
  using ConfiguringEnvironmentLauncher =
      std::shared_ptr<fidl::SynchronousInterfacePtr<fuchsia::sys::Launcher>>;
  using Promise = fit::promise<void, SandboxResult>;
  using PromiseResult = fit::result<void, SandboxResult>;

  void StartEnvironments();
  void Terminate(SandboxResult result);
  void Terminate(SandboxResult::Status status, std::string description = std::string());
  void PostTerminate(SandboxResult result);
  void PostTerminate(SandboxResult::Status status, std::string description = std::string());

  void EnableTestObservation();
  void RegisterTest(size_t ticket);
  void UnregisterTest(size_t ticket);

  template <typename T>
  bool LaunchProcess(fuchsia::sys::LauncherSyncPtr* launcher, const std::string& url,
                     const std::vector<std::string>& arguments, bool is_test);

  Promise LaunchSetup(fuchsia::sys::LauncherSyncPtr* launcher, const std::string& url,
                      const std::vector<std::string>& arguments);

  Promise StartChildEnvironment(ConfiguringEnvironmentPtr parent,
                                const config::Environment* config);
  Promise StartEnvironmentInner(ConfiguringEnvironmentPtr environment,
                                const config::Environment* config);
  Promise LaunchGuestEnvironment(ConfiguringEnvironmentPtr env, const config::Guest& config);
  Promise SendGuestFiles(ConfiguringEnvironmentPtr env, const config::Guest& guest);
  Promise StartGuests(ConfiguringEnvironmentPtr env, const config::Config* config);
  Promise StartEnvironmentSetup(const config::Environment* config,
                                ConfiguringEnvironmentLauncher launcher);
  Promise StartEnvironmentAppsAndTests(const config::Environment* config,
                                       ConfiguringEnvironmentLauncher launcher);

  bool CreateEnvironmentOptions(const config::Environment& config,
                                ManagedEnvironment::Options* options);
  bool CreateGuestOptions(const std::vector<config::Guest>& guests,
                          ManagedEnvironment::Options* options);
  Promise ConfigureRootEnvironment();
  Promise ConfigureGuestEnvironment();
  Promise RunRootConfiguration(ManagedEnvironment::Options root_options);
  Promise RunGuestConfiguration(ManagedEnvironment::Options guest_options);
  Promise ConfigureEnvironment(ConfiguringEnvironmentPtr env, const config::Environment* config,
                               bool root = false);
  bool ConfigureNetworks();

  async_dispatcher_t* main_dispatcher_;
  std::unique_ptr<async::Loop> helper_loop_;
  std::unique_ptr<async::Executor> helper_executor_;
  config::Config env_config_;
  bool setup_done_;
  bool test_spawned_;
  SandboxEnv::Ptr sandbox_env_;
  TerminationCallback termination_callback_;
  ServicesCreatedCallback services_created_callback_;
  RootEnvironmentCreatedCallback root_environment_created_callback_;
  fuchsia::sys::EnvironmentPtr parent_env_;
  fuchsia::sys::LoaderPtr loader_;
  ManagedEnvironment::Ptr root_;
  std::shared_ptr<ManagedEnvironment> guest_;
  // keep network handles to keep objects alive
  std::vector<zx::channel> network_handles_;
  // keep component controller handles to keep processes alive
  std::vector<fuchsia::sys::ComponentControllerPtr> procs_;
  std::unordered_set<size_t> tests_;
  std::unique_ptr<NetWatcher<InMemoryDump>> net_dumps_;
  // store guest realm handle to keep guest VMs alive
  fuchsia::virtualization::RealmPtr realm_;
};

}  // namespace netemul

#endif  // SRC_CONNECTIVITY_NETWORK_TESTING_NETEMUL_RUNNER_SANDBOX_H_
