// Copyright 2020 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_DEVICES_BIN_DRIVER_MANAGER_DRIVER_RUNNER_H_
#define SRC_DEVICES_BIN_DRIVER_MANAGER_DRIVER_RUNNER_H_

#include <fuchsia/component/runner/llcpp/fidl.h>
#include <fuchsia/driver/framework/llcpp/fidl.h>
#include <fuchsia/sys2/llcpp/fidl.h>
#include <lib/async/cpp/wait.h>
#include <lib/fidl/llcpp/client.h>
#include <lib/fit/function.h>
#include <lib/inspect/cpp/inspect.h>
#include <lib/zx/status.h>

#include <unordered_map>

#include <fbl/intrusive_double_list.h>

#include "src/lib/storage/vfs/cpp/pseudo_dir.h"

// Note, all of the logic here assumes we are operating on a single-threaded
// dispatcher. It is not safe to use a multi-threaded dispatcher with this code.

class DriverComponent : public fidl::WireInterface<fuchsia_component_runner::ComponentController>,
                        public fbl::DoublyLinkedListable<std::unique_ptr<DriverComponent>> {
 public:
  DriverComponent(fidl::ClientEnd<fuchsia_io::Directory> exposed_dir,
                  fidl::ClientEnd<fuchsia_driver_framework::Driver> driver);
  ~DriverComponent() override;

  void set_driver_ref(
      fidl::ServerBindingRef<fuchsia_component_runner::ComponentController> driver_ref);
  void set_node_ref(fidl::ServerBindingRef<fuchsia_driver_framework::Node> node_ref);

  zx::status<> WatchDriver(async_dispatcher_t* dispatcher);

 private:
  // fidl::WireInterface<fuchsia_component_runner::ComponentController>
  void Stop(StopCompleter::Sync& completer) override;
  void Kill(KillCompleter::Sync& completer) override;

  void OnPeerClosed(async_dispatcher_t* dispatcher, async::WaitBase* wait, zx_status_t status,
                    const zx_packet_signal_t* signal);

  fidl::ClientEnd<fuchsia_io::Directory> exposed_dir_;
  fidl::ClientEnd<fuchsia_driver_framework::Driver> driver_;
  async::WaitMethod<DriverComponent, &DriverComponent::OnPeerClosed> wait_;
  std::optional<fidl::ServerBindingRef<fuchsia_component_runner::ComponentController>> driver_ref_;
  std::optional<fidl::ServerBindingRef<fuchsia_driver_framework::Node>> node_ref_;
};

class DriverHostComponent : public fbl::DoublyLinkedListable<std::unique_ptr<DriverHostComponent>> {
 public:
  DriverHostComponent(fidl::ClientEnd<fuchsia_driver_framework::DriverHost> driver_host,
                      async_dispatcher_t* dispatcher,
                      fbl::DoublyLinkedList<std::unique_ptr<DriverHostComponent>>* driver_hosts);

  zx::status<fidl::ClientEnd<fuchsia_driver_framework::Driver>> Start(
      fidl::ClientEnd<fuchsia_driver_framework::Node> node,
      fidl::VectorView<fidl::StringView> offers,
      fidl::VectorView<fuchsia_driver_framework::wire::NodeSymbol> symbols, fidl::StringView url,
      fuchsia_data::wire::Dictionary program,
      fidl::VectorView<fuchsia_component_runner::wire::ComponentNamespaceEntry> ns,
      fidl::ServerEnd<fuchsia_io::Directory> outgoing_dir,
      fidl::ClientEnd<fuchsia_io::Directory> exposed_dir);

 private:
  fidl::Client<fuchsia_driver_framework::DriverHost> driver_host_;
};

class Node;

class DriverBinder {
 public:
  virtual ~DriverBinder() = default;
  // Attempt to bind `node` with given `args`.
  // The lifetime of `node` must live until `callback` is called.
  virtual void Bind(Node* node, fuchsia_driver_framework::wire::NodeAddArgs args,
                    fit::callback<void(zx::status<>)> callback) = 0;
};

class Node : public fidl::WireInterface<fuchsia_driver_framework::NodeController>,
             public fidl::WireInterface<fuchsia_driver_framework::Node>,
             public fbl::DoublyLinkedListable<std::unique_ptr<Node>> {
 public:
  using Offers = std::vector<fidl::StringView>;
  using Symbols = std::vector<fuchsia_driver_framework::wire::NodeSymbol>;

  Node(Node* parent, DriverBinder* driver_binder, async_dispatcher_t* dispatcher,
       std::string_view name);
  ~Node() override;

  const std::string& name() const;
  fidl::VectorView<fidl::StringView> offers();
  fidl::VectorView<fuchsia_driver_framework::wire::NodeSymbol> symbols();
  DriverHostComponent* parent_driver_host() const;
  void set_driver_host(DriverHostComponent* driver_host);
  void set_driver_ref(
      fidl::ServerBindingRef<fuchsia_component_runner::ComponentController> driver_ref);
  void set_node_ref(fidl::ServerBindingRef<fuchsia_driver_framework::Node> node_ref);
  void set_controller_ref(
      fidl::ServerBindingRef<fuchsia_driver_framework::NodeController> controller_ref);
  fbl::DoublyLinkedList<std::unique_ptr<Node>>& children();

  std::string TopoName() const;
  void Remove();

 private:
  void Unbind();
  // fidl::WireInterface<fuchsia_driver_framework::NodeController>
  void Remove(RemoveCompleter::Sync& completer) override;
  // fidl::WireInterface<fuchsia_driver_framework::Node>
  void AddChild(fuchsia_driver_framework::wire::NodeAddArgs args,
                fidl::ServerEnd<fuchsia_driver_framework::NodeController> controller,
                fidl::ServerEnd<fuchsia_driver_framework::Node> node,
                AddChildCompleter::Sync& completer) override;

  Node* const parent_;
  DriverBinder* const driver_binder_;
  async_dispatcher_t* const dispatcher_;

  const std::string name_;
  fidl::FidlAllocator<512> allocator_;
  Offers offers_;
  Symbols symbols_;

  DriverHostComponent* driver_host_ = nullptr;
  std::optional<fidl::ServerBindingRef<fuchsia_component_runner::ComponentController>> driver_ref_;
  std::optional<fidl::ServerBindingRef<fuchsia_driver_framework::Node>> node_ref_;
  std::optional<fidl::ServerBindingRef<fuchsia_driver_framework::NodeController>> controller_ref_;
  fbl::DoublyLinkedList<std::unique_ptr<Node>> children_;
};

struct DriverArgs {
  fidl::ClientEnd<fuchsia_io::Directory> exposed_dir;
  Node* node;
};

class DriverRunner : public fidl::WireInterface<fuchsia_component_runner::ComponentRunner>,
                     public DriverBinder {
 public:
  DriverRunner(fidl::ClientEnd<fuchsia_sys2::Realm> realm,
               fidl::ClientEnd<fuchsia_driver_framework::DriverIndex> driver_index,
               inspect::Inspector* inspector, async_dispatcher_t* dispatcher);

  fit::promise<inspect::Inspector> Inspect();
  zx::status<> PublishComponentRunner(const fbl::RefPtr<fs::PseudoDir>& svc_dir);
  zx::status<> StartRootDriver(std::string_view name);

 private:
  // fidl::WireInterface<fuchsia_component_runner::ComponentRunner>
  void Start(fuchsia_component_runner::wire::ComponentStartInfo start_info,
             fidl::ServerEnd<fuchsia_component_runner::ComponentController> controller,
             StartCompleter::Sync& completer) override;
  // DriverBinder
  void Bind(Node* node, fuchsia_driver_framework::wire::NodeAddArgs args,
            fit::callback<void(zx::status<>)> callback) override;

  zx::status<> StartDriver(Node* node, std::string_view url);

  zx::status<std::unique_ptr<DriverHostComponent>> StartDriverHost();
  zx::status<fidl::ClientEnd<fuchsia_io::Directory>> CreateComponent(std::string name,
                                                                     std::string url,
                                                                     std::string collection);
  uint64_t next_driver_host_id_ = 0;
  fidl::Client<fuchsia_sys2::Realm> realm_;
  fidl::Client<fuchsia_driver_framework::DriverIndex> driver_index_;
  async_dispatcher_t* dispatcher_;
  Node root_node_;
  std::unordered_map<std::string, DriverArgs> driver_args_;
  fbl::DoublyLinkedList<std::unique_ptr<DriverComponent>> drivers_;
  fbl::DoublyLinkedList<std::unique_ptr<DriverHostComponent>> driver_hosts_;
};

#endif  // SRC_DEVICES_BIN_DRIVER_MANAGER_DRIVER_RUNNER_H_
