// 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_COMPONENT_CONTROLLER_IMPL_H_
#define GARNET_BIN_APPMGR_COMPONENT_CONTROLLER_IMPL_H_

#include <fs/pseudo-dir.h>
#include <fuchsia/inspect/cpp/fidl.h>
#include <fuchsia/sys/cpp/fidl.h>
#include <lib/async/cpp/wait.h>
#include <lib/zx/process.h>
#include <zircon/assert.h>

#include <vector>

#include "garnet/bin/appmgr/component_container.h"
#include "garnet/bin/appmgr/debug_info_retriever.h"
#include "garnet/bin/appmgr/hub/component_hub.h"
#include "garnet/bin/appmgr/hub/hub_info.h"
#include "garnet/bin/appmgr/namespace.h"
#include "garnet/bin/appmgr/system_objects_directory.h"
#include "lib/fidl/cpp/binding.h"

namespace component {

typedef fit::function<void(int64_t, fuchsia::sys::TerminationReason,
                           fuchsia::sys::ComponentController_EventSender*)>
    TerminationCallback;

// ComponentRequestWrapper wraps failure behavior in the event a Component fails
// to start. It wraps the behavior of binding to an incoming interface request
// and sending error events to clients before closing the channel.
// If there is no error, the wrapped request and callback may be Extract()ed
// and bound to a concrete interface.
// TODO(CP-84): Solve the general problem this solves.
class ComponentRequestWrapper {
 public:
  explicit ComponentRequestWrapper(
      fidl::InterfaceRequest<fuchsia::sys::ComponentController> request,
      TerminationCallback callback, int64_t default_return = -1,
      fuchsia::sys::TerminationReason default_reason =
          fuchsia::sys::TerminationReason::UNKNOWN);
  ~ComponentRequestWrapper();
  ComponentRequestWrapper(ComponentRequestWrapper&& other);
  void operator=(ComponentRequestWrapper&& other);

  void SetReturnValues(int64_t return_code,
                       fuchsia::sys::TerminationReason reason);

  bool Extract(
      fidl::InterfaceRequest<fuchsia::sys::ComponentController>* out_request,
      TerminationCallback* out_callback) {
    if (!active_) {
      return false;
    }
    *out_request = std::move(request_);
    *out_callback = std::move(callback_);
    active_ = false;
    return true;
  }

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ComponentRequestWrapper);

 private:
  fidl::InterfaceRequest<fuchsia::sys::ComponentController> request_;
  TerminationCallback callback_;
  int64_t return_code_;
  fuchsia::sys::TerminationReason reason_;
  bool active_ = true;
};

// Construct a callback that forwards termination information back over an
// incoming ComponentController_EventSender , if it exists.
TerminationCallback MakeForwardingTerminationCallback();

// FailedComponentController implements the component controller interface for
// components that failed to start. This class serves the purpose of actually
// binding to a ComponentController channel and passing back a termination
// event.
class FailedComponentController : public fuchsia::sys::ComponentController {
 public:
  FailedComponentController(
      int64_t return_code, fuchsia::sys::TerminationReason termination_reason,
      TerminationCallback termination_callback,
      fidl::InterfaceRequest<fuchsia::sys::ComponentController> controller);
  virtual ~FailedComponentController();
  void Kill() override;
  void Detach() override;

 private:
  fidl::Binding<fuchsia::sys::ComponentController> binding_;
  int64_t return_code_;
  fuchsia::sys::TerminationReason termination_reason_;
  TerminationCallback termination_callback_;
};

class ComponentControllerBase : public fuchsia::sys::ComponentController {
 public:
  ComponentControllerBase(
      fidl::InterfaceRequest<fuchsia::sys::ComponentController> request,
      std::string url, std::string args, std::string label,
      std::string hub_instance_id, fxl::RefPtr<Namespace> ns,
      zx::channel exported_dir, zx::channel client_request);
  virtual ~ComponentControllerBase() override;

 public:
  HubInfo HubInfo();
  const std::string& label() const { return label_; }
  const fbl::RefPtr<fs::PseudoDir>& hub_dir() const { return hub_.dir(); }

  // |fuchsia::sys::ComponentController| implementation:
  void Detach() override;

 protected:
  ComponentHub* hub() { return &hub_; }

  // Returns the incoming services from the namespace.
  const fbl::RefPtr<ServiceProviderDirImpl>& incoming_services() const {
    ZX_DEBUG_ASSERT(ns_);
    return ns_->services();
  };

  fidl::Binding<fuchsia::sys::ComponentController> binding_;

 private:
  std::string label_;
  std::string hub_instance_id_;

  ComponentHub hub_;

  fxl::RefPtr<Namespace> ns_;

  fuchsia::io::NodePtr cloned_exported_dir_;

  fuchsia::io::DirectoryPtr exported_dir_;

  fuchsia::inspect::InspectPtr inspect_checker_;
};

class ComponentControllerImpl : public ComponentControllerBase {
 public:
  ComponentControllerImpl(
      fidl::InterfaceRequest<fuchsia::sys::ComponentController> request,
      ComponentContainer<ComponentControllerImpl>* container, zx::job job,
      zx::process process, std::string url, std::string args, std::string label,
      fxl::RefPtr<Namespace> ns, zx::channel exported_dir,
      zx::channel client_request, TerminationCallback termination_callback);
  ~ComponentControllerImpl() override;

  const std::string& koid() const { return koid_; }

  zx_status_t AddSubComponentHub(const component::HubInfo& hub_info);
  zx_status_t RemoveSubComponentHub(const component::HubInfo& hub_info);

  // |fuchsia::sys::ComponentController| implementation:
  void Kill() override;

 private:
  void Handler(async_dispatcher_t* dispatcher, async::WaitBase* wait,
               zx_status_t status, const zx_packet_signal* signal);

  bool SendReturnCodeIfTerminated();

  ComponentContainer<ComponentControllerImpl>* container_;
  zx::job job_;
  zx::process process_;
  const std::string koid_;

  async::WaitMethod<ComponentControllerImpl, &ComponentControllerImpl::Handler>
      wait_;

  TerminationCallback termination_callback_;

  SystemObjectsDirectory system_objects_directory_;

  fidl::BindingSet<fuchsia::inspect::Inspect,
                   std::shared_ptr<component::Object>>
      system_directory_bindings_;

  FXL_DISALLOW_COPY_AND_ASSIGN(ComponentControllerImpl);
};

// This class acts as a bridge between the components created by ComponentRunner
// and |request|.
class ComponentBridge : public ComponentControllerBase {
 public:
  ComponentBridge(
      fidl::InterfaceRequest<fuchsia::sys::ComponentController> request,
      fuchsia::sys::ComponentControllerPtr remote_controller,
      ComponentContainer<ComponentBridge>* container, std::string url,
      std::string args, std::string label, std::string hub_instance_id,
      fxl::RefPtr<Namespace> ns, zx::channel exported_dir,
      zx::channel client_request, TerminationCallback termination_callback);

  ~ComponentBridge() override;

  void SetParentJobId(const std::string& id);

  // Set the termination reason for this bridge.
  // This should be used when a runner itself terminates and needs to report
  // back a failure over the bridge when it is closed.
  void SetTerminationReason(fuchsia::sys::TerminationReason termination_reason);

  // |fuchsia::sys::ComponentController| implementation:
  void Kill() override;

  void OnTerminated(OnTerminatedCallback callback) {
    on_terminated_event_ = std::move(callback);
  }

 private:
  fuchsia::sys::ComponentControllerPtr remote_controller_;
  ComponentContainer<ComponentBridge>* container_;
  TerminationCallback termination_callback_;
  fuchsia::sys::TerminationReason termination_reason_;
  OnTerminatedCallback on_terminated_event_;

  FXL_DISALLOW_COPY_AND_ASSIGN(ComponentBridge);
};

}  // namespace component

#endif  // GARNET_BIN_APPMGR_COMPONENT_CONTROLLER_IMPL_H_
