// 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_DRIVER2_DRIVER_BASE_H_
#define LIB_DRIVER2_DRIVER_BASE_H_

#include <fidl/fuchsia.driver.framework/cpp/fidl.h>
#include <lib/driver2/driver_context.h>
#include <lib/driver2/logger.h>
#include <lib/driver2/namespace.h>
#include <lib/driver2/outgoing_directory.h>
#include <lib/driver2/record.h>
#include <lib/driver2/start_args.h>
#include <lib/fdf/cpp/dispatcher.h>
#include <lib/sys/component/cpp/structured_config.h>

namespace driver {

using DriverStartArgs = fuchsia_driver_framework::DriverStartArgs;

// |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 two virtual methods, |Start| which must be overridden,
// and |Stop| which is optional to override.
//
// In order to work with the default |BasicFactory| factory implementation,
// 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::UnownedDispatcher driver_dispatcher);
//
// Otherwise a custom factory must be created and used to call constructors of any other shape.
//
// The following illustrates an example:
//
// ```
// class MyDriver : public driver::DriverBase {
//  public:
//   MyDriver(driver::DriverStartArgs start_args, fdf::UnownedDispatcher driver_dispatcher)
//       : driver::DriverBase("my_driver", std::move(start_args), std::move(driver_dispatcher)) {}
//
//   zx::status<> Start() override {
//     context().incoming()->Connect(...);
//     context().outgoing()->AddService(...);
//     FDF_LOG(INFO, "hello world!");
//     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_;
// };
// ```
class DriverBase {
 public:
  DriverBase(std::string_view name, DriverStartArgs start_args,
             fdf::UnownedDispatcher driver_dispatcher)
      : start_args_(std::move(start_args)),
        driver_dispatcher_(std::move(driver_dispatcher)),
        dispatcher_(driver_dispatcher_->async_dispatcher()),
        driver_context_(driver_dispatcher_->get()) {
    auto ns = std::move(start_args_.ns());
    ZX_ASSERT(ns.has_value());
    Namespace incoming = Namespace::Create(ns.value()).value();
    logger_ = Logger::Create(incoming, dispatcher_, name).value();

    auto outgoing_request = std::move(start_args_.outgoing_dir());
    ZX_ASSERT(outgoing_request.has_value());
    driver_context_.InitializeAndServe(std::move(incoming), std::move(outgoing_request.value()));
  }

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

  virtual ~DriverBase() = default;

  // This method will be called by the factory to start the driver. This is when
  // the driver should setup the outgoing directory through `context()->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.
  virtual zx::status<> Start() = 0;

  virtual void Stop() {}

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

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

  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();
  }

  template <typename StructuredConfig>
  StructuredConfig take_config() {
    static_assert(component::IsDriverStructuredConfigV<StructuredConfig>,
                  "Invalid type supplied. StructuredConfig must be a driver flavored "
                  "structured config type. Example usage: take_config<my_driverconfig::Config>().");
    return StructuredConfig::TakeFromStartArgs(start_args_);
  }

  DriverContext& context() { return driver_context_; }
  const DriverContext& context() const { return driver_context_; }

  fdf::UnownedDispatcher& driver_dispatcher() { return driver_dispatcher_; }
  const fdf::UnownedDispatcher& driver_dispatcher() const { return driver_dispatcher_; }

  async_dispatcher_t* dispatcher() { return dispatcher_; }
  const async_dispatcher_t* dispatcher() const { return dispatcher_; }

  std::optional<fuchsia_data::Dictionary>& program() { return start_args_.program(); }
  const std::optional<fuchsia_data::Dictionary>& program() const { return start_args_.program(); }

  std::optional<std::string>& url() { return start_args_.url(); }
  const std::optional<std::string>& url() const { return start_args_.url(); }

  std::optional<std::string>& node_name() { return start_args_.node_name(); }
  const std::optional<std::string>& node_name() const { return start_args_.node_name(); }

  std::optional<std::vector<fuchsia_driver_framework::NodeSymbol>>& symbols() {
    return start_args_.symbols();
  }

  const std::optional<std::vector<fuchsia_driver_framework::NodeSymbol>>& symbols() const {
    return start_args_.symbols();
  }

 private:
  DriverStartArgs start_args_;
  fdf::UnownedDispatcher driver_dispatcher_;
  async_dispatcher_t* dispatcher_;
  DriverContext driver_context_;
};

// This is the default Factory that is used to Create a Driver of type |Driver|, that inherits the
// |DriverBase| class. |Driver| must implement a constructor with the following
// signature and forward said parameters to the |DriverBase| base class:
//
//   T(DriverStartArgs start_args, fdf::UnownedDispatcher driver_dispatcher);
template <typename Driver>
class BasicFactory {
  static_assert(std::is_base_of_v<DriverBase, Driver>, "Driver has to inherit from DriverBase");
  static_assert(std::is_constructible_v<Driver, DriverStartArgs, fdf::UnownedDispatcher>,
                "Driver must contain a constructor with the signature '(driver::DriverStartArgs, "
                "fdf::UnownedDispatcher)' in order to be used with the BasicFactory.");

 public:
  static zx::status<std::unique_ptr<DriverBase>> CreateDriver(
      DriverStartArgs start_args, fdf::UnownedDispatcher driver_dispatcher) {
    std::unique_ptr<DriverBase> driver =
        std::make_unique<Driver>(std::move(start_args), std::move(driver_dispatcher));
    auto result = driver->Start();
    if (result.is_error()) {
      FDF_LOGL(WARNING, driver->logger(), "Failed to Start driver: %s", result.status_string());
      return result.take_error();
    }

    return zx::ok(std::move(driver));
  }
};

// |Record| implements static |Start| and |Stop| methods which will be used by the framework.
//
// By default, it will utilize |BasicFactory| to construct your primary driver class, |Driver|,
// and invoke it's |Start| and |Stop| methods.
//
// |Driver| must inherit from |DriverBase|. If provided, |Factory| must implement a
// public |CreateDriver| function with the following signature:
// ```
// static zx::status<std::unique_ptr<DriverBase>> CreateDriver(
//     DriverStartArgs start_args, fdf::UnownedDispatcher driver_dispatcher)
// ```
//
// This illustrates how to use a |Record| with the default |BasicFactory|:
// ```
// FUCHSIA_DRIVER_RECORD_CPP_V2(driver::Record<MyDriver>);
// ```
//
// This illustrates how to use a |Record| with a custom factory:
// ```
// class CustomFactory {
//  public:
//   static zx::status<std::unique_ptr<DriverBase>> CreateDriver(
//       DriverStartArgs start_args, fdf::UnownedDispatcher driver_dispatcher)
//   ...construct and start driver...
// };
// // We must define the record before passing into the macro, otherwise the macro expansion
// // will think the comma is to pass a second macro argument.
// using record = driver::Record<MyDriver, CustomFactory>;
// FUCHSIA_DRIVER_RECORD_CPP_V2(record);
// ```
template <typename Driver, typename Factory = BasicFactory<Driver>>
class Record {
  static_assert(std::is_base_of_v<DriverBase, Driver>, "Driver has to inherit from DriverBase");

  DECLARE_HAS_MEMBER_FN(has_create_driver, CreateDriver);
  static_assert(has_create_driver_v<Factory>,
                "Factory must implement a public static CreateDriver function.");
  static_assert(
      std::is_same_v<decltype(&Factory::CreateDriver),
                     zx::status<std::unique_ptr<DriverBase>> (*)(
                         DriverStartArgs start_args, fdf::UnownedDispatcher driver_dispatcher)>,
      "CreateDriver must be a public static function with signature "
      "'zx::status<std::unique_ptr<driver::DriverBase>> (driver::DriverStartArgs start_args, "
      "fdf::UnownedDispatcher driver_dispatcher)'.");

 public:
  static zx_status_t Start(EncodedDriverStartArgs encoded_start_args, fdf_dispatcher_t* dispatcher,
                           void** driver) {
    // Decode the incoming `msg`.
    auto wire_format_metadata =
        fidl::WireFormatMetadata::FromOpaque(encoded_start_args.wire_format_metadata);
    fit::result start_args = fidl::Decode<fuchsia_driver_framework::DriverStartArgs>(
        fidl::EncodedMessage::FromEncodedCMessage(encoded_start_args.msg), wire_format_metadata);
    if (!start_args.is_ok()) {
      return start_args.error_value().status();
    }

    zx::status<std::unique_ptr<DriverBase>> created_driver =
        Factory::CreateDriver(std::move(*start_args), fdf::UnownedDispatcher(dispatcher));

    if (created_driver.is_error()) {
      return created_driver.status_value();
    }

    // Store `driver` pointer.
    *driver = (*created_driver).release();
    return ZX_OK;
  }

  static zx_status_t Stop(void* driver) {
    DriverBase* casted_driver = static_cast<DriverBase*>(driver);
    casted_driver->Stop();
    delete casted_driver;
    return ZX_OK;
  }
};

#define FUCHSIA_DRIVER_RECORD_CPP_V2(record) \
  FUCHSIA_DRIVER_RECORD_V1(.start = record::Start, .stop = record::Stop)

}  // namespace driver

#endif  // LIB_DRIVER2_DRIVER_BASE_H_
