// Copyright 2018 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_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_BREDR_COMMAND_HANDLER_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_BREDR_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/channel_configuration.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/command_handler.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/l2cap.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/signaling_channel.h"

namespace bt {
namespace l2cap {
namespace internal {

// Wrapper for a BR/EDR signaling channel that sends and receives command
// transactions.
class BrEdrCommandHandler final : public CommandHandler {
 public:
  class ConnectionResponse final : public Response {
   public:
    using PayloadT = ConnectionResponsePayload;
    static constexpr const char* kName = "Connection Response";

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

    ConnectionResult result() const { return result_; }
    ConnectionStatus conn_status() const { return conn_status_; }

   private:
    ConnectionResult result_;
    ConnectionStatus conn_status_;
  };

  class ConfigurationResponse final : public Response {
   public:
    using PayloadT = ConfigurationResponsePayload;
    static constexpr const char* kName = "Configuration Response";

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

    uint16_t flags() const { return flags_; }
    ConfigurationResult result() const { return result_; }
    const ChannelConfiguration& config() const { return config_; }

   private:
    friend class BrEdrCommandHandler;

    uint16_t flags_;
    ConfigurationResult result_;
    ChannelConfiguration config_;
  };

  class InformationResponse final : public Response {
   public:
    using PayloadT = InformationResponsePayload;
    static constexpr const char* kName = "Information Response";

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

    InformationType type() const { return type_; }
    InformationResult result() const { return result_; }

    uint16_t connectionless_mtu() const {
      ZX_ASSERT(result() == InformationResult::kSuccess);
      ZX_ASSERT(type() == InformationType::kConnectionlessMTU);
      return data_.As<uint16_t>();
    }

    ExtendedFeatures extended_features() const {
      ZX_ASSERT(result() == InformationResult::kSuccess);
      ZX_ASSERT(type() == InformationType::kExtendedFeaturesSupported);
      return data_.As<ExtendedFeatures>();
    }

    FixedChannelsSupported fixed_channels() const {
      ZX_ASSERT(result() == InformationResult::kSuccess);
      ZX_ASSERT(type() == InformationType::kFixedChannelsSupported);
      return data_.As<FixedChannelsSupported>();
    }

   private:
    friend class BrEdrCommandHandler;

    InformationType type_;
    InformationResult result_;

    // View into the payload received from the peer in host endianness. It is
    // only valid for the duration of the InformationResponseCallback
    // invocation.
    BufferView data_;
  };

  using ConnectionResponseCallback = fit::function<SignalingChannelInterface::ResponseHandlerAction(
      const ConnectionResponse& rsp)>;
  using ConfigurationResponseCallback =
      fit::function<ResponseHandlerAction(const ConfigurationResponse& rsp)>;
  // Information Responses never have additional responses.
  using InformationResponseCallback = fit::function<void(const InformationResponse& rsp)>;

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

    void Send(ChannelId local_cid, ConnectionResult result, ConnectionStatus status);
  };

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

    void Send(ChannelId remote_cid, uint16_t flags, ConfigurationResult result,
              ChannelConfiguration::ConfigurationOptions options);
  };

  class InformationResponder final : public Responder {
   public:
    InformationResponder(SignalingChannel::Responder* sig_responder, InformationType type);

    void SendNotSupported();

    void SendConnectionlessMtu(uint16_t mtu);

    void SendExtendedFeaturesSupported(ExtendedFeatures extended_features);

    void SendFixedChannelsSupported(FixedChannelsSupported channels_supported);

   private:
    void Send(InformationResult result, const ByteBuffer& data);
    InformationType type_;
  };

  using ConnectionRequestCallback =
      fit::function<void(PSM psm, ChannelId remote_cid, ConnectionResponder* responder)>;
  using ConfigurationRequestCallback =
      fit::function<void(ChannelId local_cid, uint16_t flags, ChannelConfiguration config,
                         ConfigurationResponder* responder)>;
  using InformationRequestCallback =
      fit::function<void(InformationType type, InformationResponder* responder)>;

  // |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 BrEdrCommandHandler(SignalingChannelInterface* sig,
                               fit::closure request_fail_callback = nullptr);
  ~BrEdrCommandHandler() = default;

  // Disallow copy even though there's no state because having multiple
  // BrEdrCommandHandlers in the same scope is likely due to a bug or is at
  // least redundant.
  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(BrEdrCommandHandler);

  // Outbound request sending methods. Response callbacks are required to be
  // non-empty. The callbacks are wrapped and moved into the SignalingChannel
  // and may outlive BrEdrCommandHandler.
  bool SendConnectionRequest(uint16_t psm, ChannelId local_cid, ConnectionResponseCallback cb);
  bool SendConfigurationRequest(ChannelId remote_cid, uint16_t flags,
                                ChannelConfiguration::ConfigurationOptions options,
                                ConfigurationResponseCallback cb);
  bool SendInformationRequest(InformationType type, InformationResponseCallback cb);

  // Inbound request delegate registration methods. The callbacks are wrapped
  // and moved into the SignalingChannel and may outlive BrEdrCommandHandler. It
  // is expected that any request delegates registered will span the lifetime of
  // its signaling channel and hence link, so no unregistration is provided.
  // However each call to register will replace any currently registered request
  // delegate.
  void ServeConnectionRequest(ConnectionRequestCallback cb);
  void ServeConfigurationRequest(ConfigurationRequestCallback cb);
  void ServeInformationRequest(InformationRequestCallback cb);
};

}  // namespace internal
}  // namespace l2cap
}  // namespace bt

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_L2CAP_BREDR_COMMAND_HANDLER_H_
