// Copyright 2022 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 LIB_DRIVER_COMPONENT_CPP_DRIVER_BASE_H_
#define LIB_DRIVER_COMPONENT_CPP_DRIVER_BASE_H_

#include <fidl/fuchsia.driver.framework/cpp/natural_types.h>
#include <lib/component/outgoing/cpp/structured_config.h>
#include <lib/driver/component/cpp/prepare_stop_completer.h>
#include <lib/driver/component/cpp/start_completer.h>
#include <lib/driver/incoming/cpp/namespace.h>
#include <lib/driver/incoming/cpp/service_validator.h>
#include <lib/driver/logging/cpp/logger.h>
#include <lib/driver/node/cpp/add_child.h>
#include <lib/driver/outgoing/cpp/outgoing_directory.h>
#include <lib/fdf/cpp/dispatcher.h>
#include <lib/fit/function.h>
#include <lib/inspect/component/cpp/component.h>
#include <lib/stdcompat/span.h>
#include <zircon/availability.h>

#include <memory>
#include <unordered_map>

namespace fdf_internal {
template <typename DriverBaseImpl>
class DriverServer;
}  // namespace fdf_internal

namespace fdf {

using DriverStartArgs = fuchsia_driver_framework::DriverStartArgs;

#if FUCHSIA_API_LEVEL_LESS_THAN(NEXT)
// Used to indicate if we should wait for the initial interest change for the driver's logger.
extern bool logger_wait_for_initial_interest;
#endif

// |DriverBase| is an interface that drivers should inherit from. It provides methods
// for accessing the start args, as well as helper methods for common initialization tasks.
//
// There are four virtual methods:
// |Start| which must be overridden.
// |PrepareStop|, |Stop|, and the destructor |~DriverBase|, are optional to override.
//
// In order to work with the default FUCHSIA_DRIVER_EXPORT macro,
// classes which inherit from |DriverBase| must implement a constructor with the following
// signature and forward said parameters to the |DriverBase| base class:
//
//   T(DriverStartArgs start_args, fdf::UnownedSynchronizedDispatcher driver_dispatcher);
//
// The following illustrates an example:
//
// ```
// class MyDriver : public fdf::DriverBase {
//  public:
//   MyDriver(fdf::DriverStartArgs start_args, fdf::UnownedSynchronizedDispatcher driver_dispatcher)
//       : fdf::DriverBase("my_driver", std::move(start_args), std::move(driver_dispatcher)) {}
//
//   zx::result<> Start() override {
//     incoming()->Connect(...);
//     outgoing()->AddService(...);
//     FDF_LOG(INFO, "hello world!");
//     inspector().Health().Ok();
//     node_client_.Bind(std::move(node()), dispatcher());
//
//     /* Ensure all capabilities offered have been added to the outgoing directory first. */
//     auto add_result = node_client_->AddChild(...); if (add_result.is_error()) {
//       /* Releasing the node channel signals unbind to DF. */
//       node_client_.AsyncTeardown(); // Or node().reset() if we hadn't moved it into the client.
//       return add_result.take_error();
//     }
//
//     return zx::ok();
//   }
//  private:
//   fidl::SharedClient<fuchsia_driver_framework::Node> node_client_;
// };
// ```
//
// # Thread safety
//
// This class is thread-unsafe. Instances must be managed and used from tasks
// running on the |driver_dispatcher|, and the dispatcher must be synchronized.
// See
// https://fuchsia.dev/fuchsia-src/development/languages/c-cpp/thread-safe-async#synchronized-dispatcher
class DriverBase {
 public:
  // Gets the DriverBase instance from the given token. This is only intended for testing.
  template <typename DriverBaseImpl>
  static DriverBaseImpl* GetInstanceFromTokenForTesting(void* token) {
    fdf_internal::DriverServer<DriverBaseImpl>* driver_server =
        static_cast<fdf_internal::DriverServer<DriverBaseImpl>*>(token);
    return static_cast<DriverBaseImpl*>(driver_server->GetDriverBaseImpl());
  }

  DriverBase(std::string_view name, DriverStartArgs start_args,
             fdf::UnownedSynchronizedDispatcher driver_dispatcher);

  DriverBase(const DriverBase&) = delete;
  DriverBase& operator=(const DriverBase&) = delete;

  // The destructor is called right after the |Stop| method.
  virtual ~DriverBase();

  // This method will be called by the factory to start the driver. This is when
  // the driver should setup the outgoing directory through `outgoing()->Add...` calls.
  // Do not call Serve, as it has already been called by the |DriverBase| constructor.
  // Child nodes can be created here synchronously or asynchronously as long as all of the
  // protocols being offered to the child has been added to the outgoing directory first.
  // There are two versions of this method which may be implemented depending on whether Start would
  // like to complete synchronously or asynchronously. The driver may override either one of these
  // methods, but must implement one. The asynchronous version will be called over the synchronous
  // version if both are implemented.
  virtual zx::result<> Start() { return zx::error(ZX_ERR_NOT_SUPPORTED); }
  virtual void Start(StartCompleter completer) { completer(Start()); }

  // This provides a way for the driver to asynchronously prepare to stop. The driver should
  // initiate any teardowns that need to happen on the driver dispatchers. Once it is ready to stop,
  // the completer's Complete function can be called (from any thread/context) with a result.
  // After the completer is called, the framework will shutdown all of the driver's fdf dispatchers
  // and deallocate the driver.
  virtual void PrepareStop(PrepareStopCompleter completer) { completer(zx::ok()); }

  // This is called after all the driver dispatchers belonging to this driver have been shutdown.
  // This ensures that there are no pending tasks on any of the driver dispatchers that will access
  // the driver after it has been destroyed.
  virtual void Stop() {}

  // This can be used to log in driver factories:
  // `FDF_LOGL(INFO, driver->logger(), "...");`
  Logger& logger() { return *logger_; }

  using InitMethodCallback = fit::callback<zx::result<>(async_dispatcher_t*, Namespace&)>;

  // Callbacks that are invoked prior to the start hook.
  void RegisterInitMethods(InitMethodCallback cb);

  // Runs methods registered. Meant to be invoked prior to the start hook.
  zx::result<> RunInitMethods();

 protected:
  // The logger can't be private because the logging macros rely on it.
  // NOLINTNEXTLINE(misc-non-private-member-variables-in-classes)
  std::unique_ptr<Logger> logger_;

  // Client to the `fuchsia.driver.framework/Node` protocol provided by the driver framework.
  // This can be used to add children to the node that the driver is bound to.
  fidl::ClientEnd<fuchsia_driver_framework::Node>& node() {
    auto& node = start_args_.node();
    ZX_ASSERT(node.has_value());
    return node.value();
  }

  const fidl::ClientEnd<fuchsia_driver_framework::Node>& node() const {
    auto& node = start_args_.node();
    ZX_ASSERT(node.has_value());
    return node.value();
  }

  const std::vector<fuchsia_driver_framework::Offer>& node_offers() {
    auto& node_offers = start_args_.node_offers();
    ZX_ASSERT(node_offers.has_value());
    return node_offers.value();
  }

  template <typename StructuredConfig>
  StructuredConfig take_config() {
    static_assert(component::IsStructuredConfigV<StructuredConfig>,
                  "Invalid type supplied. StructuredConfig must be a "
                  "structured config type. Example usage: take_config<my_driverconfig::Config>().");
    std::optional config_vmo = std::move(start_args_.config());
    ZX_ASSERT_MSG(config_vmo.has_value(),
                  "Config VMO handle must be provided and cannot already have been taken.");
    return StructuredConfig::CreateFromVmo(std::move(config_vmo.value()));
  }

  // The name of the driver that is given to the DriverBase constructor.
  std::string_view name() const { return name_; }

  // Used to access the incoming namespace of the driver. This allows connecting to both zircon and
  // driver transport incoming services.
  const std::shared_ptr<Namespace>& incoming() const { return incoming_; }

  // The `/svc` directory in the incoming namespace.
  fidl::UnownedClientEnd<fuchsia_io::Directory> svc() const { return incoming_->svc_dir(); }

  // Used to access the outgoing directory that the driver is serving. Can be used to add both
  // zircon and driver transport outgoing services.
  std::shared_ptr<OutgoingDirectory>& outgoing() { return outgoing_; }

  // The unowned synchronized driver dispatcher that the driver is started with.
  const fdf::UnownedSynchronizedDispatcher& driver_dispatcher() const { return driver_dispatcher_; }

  // The async_dispatcher_t interface of the synchronized driver dispatcher that the driver
  // is started with.
  async_dispatcher_t* dispatcher() const { return dispatcher_; }

  // The program dictionary in the start args.
  // This is the `program` entry in the cml of the driver.
  const std::optional<fuchsia_data::Dictionary>& program() const { return start_args_.program(); }

  // The url field in the start args.
  // This is the URL of the package containing the driver. This is purely informational,
  // used only to provide data for inspect.
  const std::optional<std::string>& url() const { return start_args_.url(); }

  // The node_name field in the start args.
  // This is the name of the node that the driver is bound to.
  const std::optional<std::string>& node_name() const { return start_args_.node_name(); }

#if FUCHSIA_API_LEVEL_AT_MOST(26)
  // Returns the node properties of the node the driver is bound to or its parents.
  // Returns the node's own node properties if `parent_node_name` is "default" and the node is a
  // non-composite.
  // Returns the node's primary parent's node properties if `parent_node_name` is "default" and the
  // node is a composite.
  // Returns an empty vector if the parent does not exist.
  cpp20::span<const fuchsia_driver_framework::NodeProperty> node_properties(
      const std::string& parent_node_name = "default") const;
#endif

  // Returns the node properties of the node the driver is bound to or its parents.
  // Returns the node's own node properties if `parent_node_name` is "default" and the node is a
  // non-composite.
  // Returns the node's primary parent's node properties if `parent_node_name` is "default" and the
  // node is a composite.
  // Returns an empty vector if the parent does not exist.
  cpp20::span<const fuchsia_driver_framework::NodeProperty2> node_properties_2(
      const std::string& parent_node_name = "default") const;

  // The symbols field in the start args.
  // These come from the driver that added |node|, and are filtered to the symbols requested in the
  // bind program.
  const std::optional<std::vector<fuchsia_driver_framework::NodeSymbol>>& symbols() const {
    return start_args_.symbols();
  }

  // A component-wide Inspector for the driver.
  inspect::ComponentInspector& inspector() {
    if (!inspector_.has_value()) {
      InitInspectorExactlyOnce({});
    }

    return *inspector_;
  }

  // Initialize the driver's Inspector exactly one time.
  //
  // To avoid data races, subsequent calls are ignored are not an error.
  void InitInspectorExactlyOnce(inspect::Inspector inspector);

  // Creates an owned child node on the node that the driver is bound to. The driver framework will
  // NOT try to match and bind a driver to this child as it is owned by the current driver.
  //
  // The |node()| must not have been moved out manually by the user. This is a synchronous call
  // and requires that the dispatcher allow sync calls.
  zx::result<OwnedChildNode> AddOwnedChild(std::string_view node_name);

  // Creates a child node with the given offers and properties on the node that the driver is
  // bound to. The driver framework will try to match and bind a driver to this child.
  //
  // The |node()| must not have been moved out manually by the user. This is a synchronous call
  // and requires that the dispatcher allow sync calls.
  zx::result<fidl::ClientEnd<fuchsia_driver_framework::NodeController>> AddChild(
      std::string_view node_name,
      cpp20::span<const fuchsia_driver_framework::NodeProperty> properties,
      cpp20::span<const fuchsia_driver_framework::Offer> offers);

  // Creates an owned child node with devfs support on the node that the driver is bound to. The
  // driver framework will NOT try to match and bind a driver to this child as it is already owned
  // by the current driver.
  //
  // The |node()| must not have been moved out manually by the user. This is a synchronous call
  // and requires that the dispatcher allow sync calls.
  zx::result<OwnedChildNode> AddOwnedChild(std::string_view node_name,
                                           fuchsia_driver_framework::DevfsAddArgs& devfs_args);

  // Creates a child node with devfs support and the given offers and properties on the node that
  // the driver is bound to. The driver framework will try to match and bind a driver to this child.
  //
  // The |node()| must not have been moved out manually by the user. This is a synchronous call
  // and requires that the dispatcher allow sync calls.
  zx::result<fidl::ClientEnd<fuchsia_driver_framework::NodeController>> AddChild(
      std::string_view node_name, fuchsia_driver_framework::DevfsAddArgs& devfs_args,
      cpp20::span<const fuchsia_driver_framework::NodeProperty> properties,
      cpp20::span<const fuchsia_driver_framework::Offer> offers);

  zx::result<fidl::ClientEnd<fuchsia_driver_framework::NodeController>> AddChild(
      std::string_view node_name,
      cpp20::span<const fuchsia_driver_framework::NodeProperty2> properties,
      cpp20::span<const fuchsia_driver_framework::Offer> offers);

  zx::result<fidl::ClientEnd<fuchsia_driver_framework::NodeController>> AddChild(
      std::string_view node_name, fuchsia_driver_framework::DevfsAddArgs& devfs_args,
      cpp20::span<const fuchsia_driver_framework::NodeProperty2> properties,
      cpp20::span<const fuchsia_driver_framework::Offer> offers);

 private:
  void InitializeAndServe(Namespace incoming,
                          fidl::ServerEnd<fuchsia_io::Directory> outgoing_directory_request);

  // This will enable validating service instance connection requests that are made to the incoming
  // namespace |incoming()|. It will ensure that the given service + instance combination is valid
  // before attempting to make a connection. If it is not a valid combination, |Connect()| attempts
  // on the namespace, will return a ZX_ERR_NOT_FOUND error immediately.
  //
  // This can be enabled by setting `service_connect_validation: "true"` in the driver cml's
  // `program` section.
  void EnableServiceValidator();

  std::string name_;
  DriverStartArgs start_args_;

#if FUCHSIA_API_LEVEL_AT_MOST(26)
  std::unordered_map<std::string, cpp20::span<const fuchsia_driver_framework::NodeProperty>>
      node_properties_;
#endif  // FUCHSIA_API_LEVEL_AT_MOST(26)

  std::unordered_map<std::string, cpp20::span<const fuchsia_driver_framework::NodeProperty2>>
      node_properties_2_;

  fdf::UnownedSynchronizedDispatcher driver_dispatcher_;
  async_dispatcher_t* dispatcher_;
  std::shared_ptr<Namespace> incoming_;
  std::shared_ptr<OutgoingDirectory> outgoing_;
  std::optional<inspect::ComponentInspector> inspector_;
  std::once_flag init_inspector_once_;

  std::vector<InitMethodCallback> init_methods_;
};

}  // namespace fdf

#endif  // LIB_DRIVER_COMPONENT_CPP_DRIVER_BASE_H_
