#ifndef SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_COMMAND_HANDLER_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_COMMAND_HANDLER_H_

#include <lib/fit/function.h>

#include <memory>

#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/l2cap.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/signaling_channel.h"

namespace bt::l2cap::internal {

// Wrapper for a signaling channel that sends and receives command
// transactions. It does not hold state. Rather, it:
// - constructs outbound request payloads and decodes/dispatches the received
//   response payloads
// - constructs request handlers that decode inbound payloads, registers the
//   handlers with SignalingChannel, and creates Responder objects that bind
//   response parameters and can be used to send appropriate response commands
// CommandHandler can be constructed for each command to be sent or each
// kind of request to register, and even ephemerally as a temporary around a
// SignalingChannel.
//
// For outbound requests, use the CommandHandler::Send*Request methods. They take parameters to be
// encoded into the request payload (with endian conversion and bounds checking) and a
// *ResponseCallback callback. When a matching response or rejection is received, the callback will
// be passed a *Response object containing the decoded command's parameters. Its |status()| shall
// be checked first to determine whether it's a rejection or response command. Return
// ResponseHandlerAction::kExpectAdditionalResponse if more request responses from the peer will
// follow, or else ResponseHandlerAction::kCompleteOutboundTransaction. Returning
// kCompleteOutboundTransaction will destroy the *ResponseCallback object.
//
// If the underlying SignalingChannel times out waiting for a response, the *ResponseCallback will
// not be called. Instead, the |request_fail_callback| that CommandHandler was constructed with will
// be called.
//
// Example:
//   DisconnectionResponseCallback rsp_cb =
//       [](const DisconnectionResponse& rsp) {
//         if (rsp.status() == Status::kReject) {
//           // Do something with rsp.reject_reason()
//         } else {
//           // Do something with rsp.local_cid() and rsp.remote_cid()
//         }
//       };
//   cmd_handler.SendDisonnectionRequest(remote_cid, local_cid, std::move(rsp_cb));
//
// For inbound requests, use the CommandHandler::Serve*Req methods. They
// each take a request-handling delegate that will be called with decoded
// parameters from the received request, as well as a *Responder object. The
// Responder can be used to send a rejection (|RejectNotUnderstood()| or
// |RejectInvalidChannelId()|) or a matching response (|Send*()|). The channel
// IDs to encode into the response will be bound to the Responder. The Responder
// is only valid during the invocation of the request handler. Its sending
// methods can be called multiple times but it does not check that a malformed
// permutation of commands are sent (e.g. multiple rejections, a rejection
// followed by a response, etc.).
//
// Example:
//  DisconnectionRequestCallback req_cb =
//      [](ChannelId local_cid, ChannelId remote_cid,
//         DisconnectionResponder* responder) {
//        // Do something with local_cid and remote_cid
//        responder->Send();  // Request's IDs already bound to responder, omit
//        // OR:
//        responder->RejectInvalidChannelId();  // Idem.
//      };
//  cmd_handler.ServeDisconnectionRequest(std::move(req_cb));
//
// For both inbound requests and responses, if the received payload data is
// insufficient in size or otherwise malformed, it will be replied to with a
// Reject Not Understood and the corresponding callback will not be invoked.
class CommandHandler {
 public:
  using Status = SignalingChannel::Status;
  using ResponseHandlerAction = SignalingChannelInterface::ResponseHandlerAction;

  // Base for all responses received, including Command Reject. If |status()|
  // evaluates as |Status::kReject|, then this holds a Command Reject; then
  // |reject_reason()| should be read and the data in the derived Response
  // object should not be accessed.
  class Response {
   public:
    explicit Response(Status status) : status_(status) {}

    Status status() const { return status_; }

    // These are valid for reading if the response format contains them;
    // otherwise, they read as kInvalidChannelId.
    ChannelId local_cid() const { return local_cid_; }
    ChannelId remote_cid() const { return remote_cid_; }

    // This is valid for reading if |status| is kReject. If its value is
    // kInvalidCID, then |local_cid| and |remote_cid| are valid for reading.
    RejectReason reject_reason() const { return reject_reason_; }

   protected:
    friend class CommandHandler;

    // Fills the reject fields of |rsp|. Returns true if successful.
    bool ParseReject(const ByteBuffer& rej_payload_buf);

    Status status_;
    ChannelId local_cid_ = kInvalidChannelId;
    ChannelId remote_cid_ = kInvalidChannelId;
    RejectReason reject_reason_;
  };

  class DisconnectionResponse final : public Response {
   public:
    using PayloadT = DisconnectionResponsePayload;
    static constexpr const char* kName = "Disconnection Response";

    using Response::Response;  // Inherit ctor
    bool Decode(const ByteBuffer& payload_buf);
  };

  // Base of response-sending objects passed to request delegates that they can
  // use to reply with a corresponding response or a rejection. This base
  // includes rejection methods because they can always be sent (but are not
  // always a reasonable reply to a given request). This also binds channel IDs
  // from the request received and uses them for the outbound response payload,
  // so that the delegate can not omit or send incorrect channel IDs.
  class Responder {
   public:
    void RejectNotUnderstood();
    void RejectInvalidChannelId();

   protected:
    explicit Responder(SignalingChannel::Responder* sig_responder,
                       ChannelId local_cid = kInvalidChannelId,
                       ChannelId remote_cid = kInvalidChannelId);
    virtual ~Responder() = default;
    DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Responder);

    ChannelId local_cid() const { return local_cid_; }
    ChannelId remote_cid() const { return remote_cid_; }

    SignalingChannel::Responder* const sig_responder_;

   private:
    ChannelId local_cid_;
    ChannelId remote_cid_;
  };

  class DisconnectionResponder final : public Responder {
   public:
    DisconnectionResponder(SignalingChannel::Responder* sig_responder, ChannelId local_cid,
                           ChannelId remote_cid);

    void Send();
  };

  // Disconnection Responses never have additional responses.
  using DisconnectionResponseCallback = fit::function<void(const DisconnectionResponse& rsp)>;
  bool SendDisconnectionRequest(ChannelId remote_cid, ChannelId local_cid,
                                DisconnectionResponseCallback cb);

  using DisconnectionRequestCallback = fit::function<void(ChannelId local_cid, ChannelId remote_cid,
                                                          DisconnectionResponder* responder)>;
  void ServeDisconnectionRequest(DisconnectionRequestCallback cb);

  // |sig| must be valid for the lifetime of this object.
  // |command_failed_callback| is called if an outbound request timed out with
  // RTX or ERTX timers after retransmission (if configured). The call may come
  // after the lifetime of this object.
  explicit CommandHandler(SignalingChannelInterface* sig,
                          fit::closure request_fail_callback = nullptr);
  virtual ~CommandHandler() = default;

 protected:
  // Returns a function that decodes a response status and payload into a |ResponseT| object and
  // invokes |rsp_cb| with it.
  // |ResponseT| needs to have
  //  - |Decode| function that accepts a buffer of at least |sizeof(ResponseT::PayloadT)| bytes. If
  //    it returns false, then decoding failed, no additional responses are expected, and the user
  //    response handler will not be called.
  //  - |kName| string literal
  //
  // TODO(36062): Name the return type of CallbackT to make parsing code more readable.
  template <class ResponseT, typename CallbackT>
  SignalingChannel::ResponseHandler BuildResponseHandler(CallbackT rsp_cb) {
    return [rsp_cb = std::move(rsp_cb), fail_cb = request_fail_callback_.share()](
               Status status, const ByteBuffer& rsp_payload) {
      if (status == Status::kTimeOut) {
        bt_log(INFO, "l2cap", "cmd: timed out waiting for \"%s\"", ResponseT::kName);
        if (fail_cb) {
          fail_cb();
        }
        return ResponseHandlerAction::kCompleteOutboundTransaction;
      }

      ResponseT rsp(status);
      if (status == Status::kReject) {
        if (!rsp.ParseReject(rsp_payload)) {
          bt_log(TRACE, "l2cap", "cmd: ignoring malformed Command Reject, size %zu",
                 rsp_payload.size());
          return ResponseHandlerAction::kCompleteOutboundTransaction;
        }
        return InvokeResponseCallback(&rsp_cb, std::move(rsp));
      }

      if (rsp_payload.size() < sizeof(typename ResponseT::PayloadT)) {
        bt_log(TRACE, "l2cap", "cmd: ignoring malformed \"%s\", size %zu (expected %zu)",
               ResponseT::kName, rsp_payload.size(), sizeof(typename ResponseT::PayloadT));
        return ResponseHandlerAction::kCompleteOutboundTransaction;
      }

      if (!rsp.Decode(rsp_payload)) {
        bt_log(TRACE, "l2cap", "cmd: ignoring malformed \"%s\", could not decode",
               ResponseT::kName);
        return ResponseHandlerAction::kCompleteOutboundTransaction;
      }

      return InvokeResponseCallback(&rsp_cb, std::move(rsp));
    };
  }

  // Invokes |rsp_cb| with |rsp|. Returns ResponseHandlerAction::kCompleteOutboundTransaction for
  // "no additional responses expected" if |rsp_cb| returns void, otherwise passes along its return
  // result. Used because not all *ResponseCallback types return void (some can request additional
  // continuations in their return value).
  template <typename CallbackT, class ResponseT>
  static CommandHandler::ResponseHandlerAction InvokeResponseCallback(CallbackT* const rsp_cb,
                                                                      ResponseT rsp) {
    if constexpr (std::is_void_v<std::invoke_result_t<CallbackT, ResponseT>>) {
      (*rsp_cb)(rsp);
      return ResponseHandlerAction::kCompleteOutboundTransaction;
    } else {
      return (*rsp_cb)(rsp);
    }
  }

  SignalingChannelInterface* sig() const { return sig_; }

 private:
  SignalingChannelInterface* const sig_;  // weak
  fit::closure request_fail_callback_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(CommandHandler);
};

}  // namespace bt::l2cap::internal

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_COMMAND_HANDLER_H_
