// 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.

#ifndef GARNET_BIN_APPMGR_REALM_H_
#define GARNET_BIN_APPMGR_REALM_H_

#include <fs/synchronous-vfs.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/fidl/cpp/binding_set.h>
#include <lib/fit/function.h>
#include <lib/fsl/vmo/file.h>
#include <lib/sys/cpp/service_directory.h>
#include <lib/zx/channel.h>
#include <src/lib/fxl/macros.h>
#include <src/lib/fxl/memory/ref_ptr.h>
#include <src/lib/fxl/strings/string_view.h>

#include <iosfwd>
#include <memory>
#include <string>
#include <unordered_map>

#include "garnet/bin/appmgr/component_container.h"
#include "garnet/bin/appmgr/component_controller_impl.h"
#include "garnet/bin/appmgr/environment_controller_impl.h"
#include "garnet/bin/appmgr/hub/hub_info.h"
#include "garnet/bin/appmgr/hub/realm_hub.h"
#include "garnet/bin/appmgr/namespace.h"
#include "garnet/bin/appmgr/namespace_builder.h"
#include "garnet/bin/appmgr/runner_holder.h"
#include "garnet/bin/appmgr/scheme_map.h"
#include "garnet/lib/cmx/runtime.h"
#include "garnet/lib/loader/package_loader.h"

namespace component {

struct RealmArgs {
  static RealmArgs Make(
      Realm* parent, std::string label, std::string data_path,
      std::string cache_path,
      const std::shared_ptr<sys::ServiceDirectory>& env_services,
      bool run_virtual_console, fuchsia::sys::EnvironmentOptions options);

  static RealmArgs MakeWithAdditionalServices(
      Realm* parent, std::string label, std::string data_path,
      std::string cache_path,
      const std::shared_ptr<sys::ServiceDirectory>& env_services,
      bool run_virtual_console,
      fuchsia::sys::ServiceListPtr additional_services,
      fuchsia::sys::EnvironmentOptions options);

  Realm* parent;
  std::string label;
  std::string data_path;
  std::string cache_path;
  std::shared_ptr<sys::ServiceDirectory> environment_services;
  bool run_virtual_console;
  fuchsia::sys::ServiceListPtr additional_services;
  fuchsia::sys::EnvironmentOptions options;
};

class Realm : public ComponentContainer<ComponentControllerImpl> {
 public:
  static std::unique_ptr<Realm> Create(RealmArgs args);

  // Constructor to create a Realm object. Clients should call |Create|.
  Realm(RealmArgs args, zx::job job);

  ~Realm();

  Realm* parent() const { return parent_; }
  const std::string& label() const { return label_; }
  const std::string& data_path() const { return data_path_; }
  const std::string& cache_path() const { return cache_path_; }
  const std::string& koid() const { return koid_; }

  const fbl::RefPtr<fs::PseudoDir>& hub_dir() const { return hub_.dir(); }

  std::shared_ptr<sys::ServiceDirectory> environment_services() const {
    return environment_services_;
  }

  HubInfo HubInfo();

  zx::job DuplicateJobForHub() const;

  const zx::job& job() const { return job_; }

  void CreateNestedEnvironment(
      fidl::InterfaceRequest<fuchsia::sys::Environment> environment,
      fidl::InterfaceRequest<fuchsia::sys::EnvironmentController>
          controller_request,
      std::string label, fuchsia::sys::ServiceListPtr additional_services,
      fuchsia::sys::EnvironmentOptions options);

  using ComponentObjectCreatedCallback =
      fit::function<void(std::weak_ptr<ComponentControllerImpl> component)>;

  void CreateComponent(
      fuchsia::sys::LaunchInfo launch_info,
      fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller,
      ComponentObjectCreatedCallback callback = nullptr);

  // Removes the child realm from this realm and returns the owning
  // reference to the child's controller. The caller of this function
  // typically destroys the controller (and hence the environment) shortly
  // after calling this function.
  std::unique_ptr<EnvironmentControllerImpl> ExtractChild(Realm* child);

  // Removes the application from this environment and returns the owning
  // reference to the application's controller. The caller of this function
  // typically destroys the controller (and hence the application) shortly after
  // calling this function.
  // We use shared_ptr so that we can pass weak_ptrs to dependent code.
  std::shared_ptr<ComponentControllerImpl> ExtractComponent(
      ComponentControllerImpl* controller) override;

  void AddBinding(
      fidl::InterfaceRequest<fuchsia::sys::Environment> environment);

  // Binds the given channel to the services directory (/svc) for the very first
  // nested realm created. This function is only supported for the root realm,
  // otherwise it will do nothing and return ZX_ERR_NOT_SUPPORTED.
  zx_status_t BindFirstNestedRealmSvc(zx::channel channel);

  void CreateShell(const std::string& path, zx::channel svc);

  void Resolve(fidl::StringPtr name,
               fuchsia::process::Resolver::ResolveCallback callback);

 private:
  static uint32_t next_numbered_label_;

  RunnerHolder* GetOrCreateRunner(const std::string& runner);
  RunnerHolder* GetRunnerRecursive(const std::string& runner) const;

  void CreateComponentWithRunnerForScheme(
      std::string runner_url, fuchsia::sys::LaunchInfo launch_info,
      ComponentRequestWrapper component_request,
      ComponentObjectCreatedCallback callback);

  void CreateComponentFromPackage(fuchsia::sys::PackagePtr package,
                                  fuchsia::sys::LaunchInfo launch_info,
                                  ComponentRequestWrapper component_request,
                                  ComponentObjectCreatedCallback callback);

  void CreateElfBinaryComponentFromPackage(
      fuchsia::sys::LaunchInfo launch_info, fsl::SizedVmo& app_data,
      const std::string& app_argv0, const std::vector<std::string>& env_vars,
      zx::channel loader_service, fdio_flat_namespace_t* flat,
      ComponentRequestWrapper component_request, fxl::RefPtr<Namespace> ns,
      ComponentObjectCreatedCallback callback);

  void CreateRunnerComponentFromPackage(
      fuchsia::sys::PackagePtr package, fuchsia::sys::LaunchInfo launch_info,
      RuntimeMetadata& runtime, fuchsia::sys::FlatNamespace flat,
      ComponentRequestWrapper component_request, fxl::RefPtr<Namespace> ns,
      fidl::VectorPtr<fuchsia::sys::ProgramMetadata> program_metadata);

  zx::channel OpenInfoDir();

  std::string IsolatedPathForPackage(std::string path_prefix,
                                     const FuchsiaPkgUrl& fp);

  Realm* const parent_;
  fuchsia::sys::LoaderPtr loader_;
  std::string label_;
  std::string data_path_;
  std::string cache_path_;
  std::string koid_;
  const bool run_virtual_console_;
  std::unique_ptr<component::PackageLoader> package_loader_;

  zx::job job_;

  fxl::RefPtr<Namespace> default_namespace_;

  RealmHub hub_;
  fs::SynchronousVfs info_vfs_;

  std::unordered_map<Realm*, std::unique_ptr<EnvironmentControllerImpl>>
      children_;

  std::unordered_map<ComponentControllerImpl*,
                     std::shared_ptr<ComponentControllerImpl>>
      applications_;

  std::unordered_map<std::string, std::unique_ptr<RunnerHolder>> runners_;

  // This channel pair is only created for the root realm, and is used to
  // implement BindFirstNestedRealmSvc. The server end is used to serve the
  // services directory (/svc) for the first nested realm created.
  zx::channel first_nested_realm_svc_client_;
  zx::channel first_nested_realm_svc_server_;

  SchemeMap scheme_map_;

  const std::shared_ptr<sys::ServiceDirectory> environment_services_;

  bool allow_parent_runners_ = false;
  bool delete_storage_on_death_ = false;

  FXL_DISALLOW_COPY_AND_ASSIGN(Realm);
};

}  // namespace component

#endif  // GARNET_BIN_APPMGR_REALM_H_
