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

#include <fuchsia/process/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>

#include <memory>
#include <string>
#include <unordered_map>
#include <vector>

#include <fs/managed_vfs.h>

#include "lib/fidl/cpp/binding_set.h"
#include "src/lib/fxl/macros.h"
#include "src/lib/fxl/memory/ref_counted.h"
#include "src/sys/appmgr/job_provider_impl.h"
#include "src/sys/appmgr/moniker.h"
#include "src/sys/appmgr/service_provider_dir_impl.h"

namespace component {
class Realm;

class Namespace : public fuchsia::sys::Environment,
                  public fuchsia::sys::Launcher,
                  public fuchsia::process::Resolver,
                  public fxl::RefCountedThreadSafe<Namespace> {
 public:
  const fbl::RefPtr<ServiceProviderDirImpl>& services() const { return services_; }
  const fbl::RefPtr<JobProviderImpl>& job_provider() { return job_provider_; }
  fxl::WeakPtr<Realm> realm() const { return realm_; }

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

  zx_status_t ServeServiceDirectory(zx::channel request);

  zx::channel OpenServicesAsDirectory();

  //
  // fuchsia::process::Resolver implementation:
  //
  void Resolve(std::string name, fuchsia::process::Resolver::ResolveCallback callback) override;

  //
  // fuchsia::sys::Environment implementation:
  //

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

  void GetLauncher(fidl::InterfaceRequest<fuchsia::sys::Launcher> launcher) override;

  void GetServices(fidl::InterfaceRequest<fuchsia::sys::ServiceProvider> services) override;

  void GetDirectory(zx::channel directory_request) override {
    ServeServiceDirectory(std::move(directory_request));
  }

  void set_component_moniker(const Moniker& moniker) { services_->set_component_moniker(moniker); }
  void set_component_id(const std::string& id) { services_->set_component_id(id); }

  //
  // fuchsia::sys::Launcher implementation:
  //

  void CreateComponent(
      fuchsia::sys::LaunchInfo launch_info,
      fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller) override;

  // Adds the service to the service directory if it's allowlisted.
  void MaybeAddComponentEventProvider();

  // Notifies a realms ComponentEventListener with the out/diagnostics directory for a component.
  void NotifyComponentDiagnosticsDirReady(const std::string& component_url,
                                          const std::string& component_name,
                                          const std::string& component_id,
                                          fidl::InterfaceHandle<fuchsia::io::Directory> directory);

  // Notifies a realms ComponentEventListener that a component started.
  void NotifyComponentStarted(const std::string& component_url, const std::string& component_name,
                              const std::string& component_id);

  // Notifies a realms ComponentEventListener that a component stopped.
  void NotifyComponentStopped(const std::string& component_url, const std::string& component_name,
                              const std::string& component_id);

  // Proccesses all pending messages and shuts downs children and self.
  // We handle shutdown here and not in realm and component as
  // 1. It is lot of work to get realm and component to maintain state and close all dependencies.
  // 2. Namespace doesn't need realm and component to be active so we can shut it down in
  // background.
  // 3. We anyways need to do this as a namespace might be dependent on a parent namespace, so
  // parent should make sure all if its child namespace shutdown before it does.
  void FlushAndShutdown(fxl::RefPtr<Namespace> self,
                        fs::ManagedVfs::CloseAllConnectionsForVnodeCallback callback = nullptr);

  // Create child namespace. Returns |null| if the namespace is shutting down.
  static fxl::RefPtr<Namespace> CreateChildNamespace(
      fxl::RefPtr<Namespace>& parent, fxl::WeakPtr<Realm> realm,
      fuchsia::sys::ServiceListPtr additional_services,
      const std::vector<std::string>* service_allowlist);

 private:
  // So that constructor with parent namesapace cannot be used directly.
  struct PrivateConstructor {};
  enum Status {
    RUNNING,
    SHUTTING_DOWN,
    STOPPED,
  };

  FRIEND_MAKE_REF_COUNTED(Namespace);
  Namespace(fxl::WeakPtr<Realm> realm, fuchsia::sys::ServiceListPtr additional_services,
            const std::vector<std::string>* service_allowlist);

  // Use CreateChildNamespace.
  Namespace(PrivateConstructor p, fxl::RefPtr<Namespace> parent, fxl::WeakPtr<Realm> realm,
            fuchsia::sys::ServiceListPtr additional_services,
            const std::vector<std::string>* service_allowlist);

  FRIEND_REF_COUNTED_THREAD_SAFE(Namespace);
  ~Namespace() override;

  void AddChild(fxl::RefPtr<Namespace> child);

  void ExtractChild(Namespace* child);
  void RunShutdownIfNoChildren();

  fidl::BindingSet<fuchsia::sys::Environment> environment_bindings_;
  fidl::BindingSet<fuchsia::sys::Launcher> launcher_bindings_;
  fidl::BindingSet<fuchsia::process::Resolver> resolver_bindings_;

  fs::ManagedVfs vfs_;
  fbl::RefPtr<ServiceProviderDirImpl> services_;
  fbl::RefPtr<JobProviderImpl> job_provider_;
  // realm_ can be null when it is shutting down and we kill namespace in background.
  fxl::WeakPtr<Realm> realm_;
  // Set if |additional_services.provider| was set.
  fuchsia::sys::ServiceProviderPtr service_provider_;
  // Set if |additional_services.host_directory| was set.
  zx::channel service_host_directory_;
  fuchsia::sys::LoaderPtr loader_;

  // Weak ptr to store in children namesapce.
  fxl::WeakPtrFactory<Namespace> weak_ptr_factory_;

  // List of children which have this namespace as its parent. Children should be shutdown before
  // this namespace is killed.
  std::map<Namespace*, fxl::RefPtr<Namespace>> children_;

  // Running status of this namespace.
  Status status_;

  // Callbacks to call when shutdown completes.
  std::vector<fs::ManagedVfs::CloseAllConnectionsForVnodeCallback> shutdown_callbacks_;

  // store parent reference
  fxl::WeakPtr<Namespace> parent_;

  // store self while shutting down.
  fxl::RefPtr<Namespace> self_for_shutdown_;

  FXL_DISALLOW_COPY_AND_ASSIGN(Namespace);
};

}  // namespace component

#endif  // SRC_SYS_APPMGR_NAMESPACE_H_
