// 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.

#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gatt/client.h"

#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/att/att.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/assert.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/log.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/slab_allocator.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/common/trace.h"
#include "src/connectivity/bluetooth/core/bt-host/public/pw_bluetooth_sapphire/internal/host/gatt/gatt_defs.h"

#pragma clang diagnostic ignored "-Wshadow"

using bt::HostError;

namespace bt::gatt {
namespace {

MutableByteBufferPtr NewPDU(size_t param_size) {
  auto pdu = NewBuffer(sizeof(att::Header) + param_size);
  if (!pdu) {
    bt_log(DEBUG, "att", "out of memory");
  }
  return pdu;
}

template <att::UUIDType Format,
          typename EntryType = att::InformationData<Format>>
bool ProcessDescriptorDiscoveryResponse(
    att::Handle range_start,
    att::Handle range_end,
    BufferView entries,
    Client::DescriptorCallback desc_callback,
    att::Handle* out_last_handle) {
  BT_DEBUG_ASSERT(out_last_handle);

  if (entries.size() % sizeof(EntryType)) {
    bt_log(DEBUG, "gatt", "malformed information data list");
    return false;
  }

  att::Handle last_handle = range_end;
  while (entries.size()) {
    const EntryType& entry = entries.To<EntryType>();

    att::Handle desc_handle = le16toh(entry.handle);

    // Stop and report an error if the server erroneously responds with
    // an attribute outside the requested range.
    if (desc_handle > range_end || desc_handle < range_start) {
      bt_log(DEBUG,
             "gatt",
             "descriptor handle out of range (handle: %#.4x, "
             "range: %#.4x - %#.4x)",
             desc_handle,
             range_start,
             range_end);
      return false;
    }

    // The handles must be strictly increasing.
    if (last_handle != range_end && desc_handle <= last_handle) {
      bt_log(DEBUG, "gatt", "descriptor handles not strictly increasing");
      return false;
    }

    last_handle = desc_handle;

    // Notify the handler.
    desc_callback(DescriptorData(desc_handle, UUID(entry.uuid)));

    entries = entries.view(sizeof(EntryType));
  }

  *out_last_handle = last_handle;
  return true;
}

}  // namespace

class Impl final : public Client {
 public:
  explicit Impl(att::Bearer::WeakPtr bearer)
      : att_(std::move(bearer)), weak_self_(this) {
    BT_DEBUG_ASSERT(att_.is_alive());

    auto handler = [this](auto txn_id, const att::PacketReader& pdu) {
      BT_DEBUG_ASSERT(pdu.opcode() == att::kNotification ||
                      pdu.opcode() == att::kIndication);

      if (pdu.payload_size() < sizeof(att::NotificationParams)) {
        // Received a malformed notification. Disconnect the link.
        bt_log(DEBUG, "gatt", "malformed notification/indication PDU");
        att_->ShutDown();
        return;
      }

      bool is_ind = pdu.opcode() == att::kIndication;
      const auto& params = pdu.payload<att::NotificationParams>();
      att::Handle handle = le16toh(params.handle);
      size_t value_size = pdu.payload_size() - sizeof(att::Handle);

      // Auto-confirm indications.
      if (is_ind) {
        auto pdu = NewPDU(0u);
        if (pdu) {
          att::PacketWriter(att::kConfirmation, pdu.get());
          att_->Reply(txn_id, std::move(pdu));
        } else {
          att_->ReplyWithError(
              txn_id, handle, att::ErrorCode::kInsufficientResources);
        }
      }

      bool maybe_truncated = false;
      // If the value is the max size that fits in the MTU, it may be truncated.
      if (value_size ==
          att_->mtu() - sizeof(att::OpCode) - sizeof(att::Handle)) {
        maybe_truncated = true;
      }

      // Run the handler
      if (notification_handler_) {
        notification_handler_(is_ind,
                              handle,
                              BufferView(params.value, value_size),
                              maybe_truncated);
      } else {
        bt_log(
            TRACE, "gatt", "dropped notification/indication without handler");
      }
    };

    not_handler_id_ = att_->RegisterHandler(att::kNotification, handler);
    ind_handler_id_ = att_->RegisterHandler(att::kIndication, handler);
  }

  ~Impl() override {
    att_->UnregisterHandler(not_handler_id_);
    att_->UnregisterHandler(ind_handler_id_);
  }

  using WeakPtr = WeakSelf<Client>::WeakPtr;
  WeakPtr GetWeakPtr() override { return weak_self_.GetWeakPtr(); }

 private:
  uint16_t mtu() const override { return att_->mtu(); }

  void ExchangeMTU(MTUCallback mtu_cb) override {
    auto pdu = NewPDU(sizeof(att::ExchangeMTURequestParams));
    if (!pdu) {
      mtu_cb(fit::error(att::Error(HostError::kOutOfMemory)));
      return;
    }

    att::PacketWriter writer(att::kExchangeMTURequest, pdu.get());
    auto params = writer.mutable_payload<att::ExchangeMTURequestParams>();
    params->client_rx_mtu = htole16(att_->preferred_mtu());

    auto rsp_cb = [this, mtu_cb = std::move(mtu_cb)](
                      att::Bearer::TransactionResult result) mutable {
      if (result.is_ok()) {
        const att::PacketReader& rsp = result.value();
        BT_DEBUG_ASSERT(rsp.opcode() == att::kExchangeMTUResponse);

        if (rsp.payload_size() != sizeof(att::ExchangeMTUResponseParams)) {
          // Received a malformed response. Disconnect the link.
          att_->ShutDown();

          mtu_cb(fit::error(att::Error(HostError::kPacketMalformed)));
          return;
        }

        const auto& rsp_params = rsp.payload<att::ExchangeMTUResponseParams>();
        uint16_t server_mtu = le16toh(rsp_params.server_rx_mtu);

        // If the minimum value is less than the default MTU, then go with the
        // default MTU (Vol 3, Part F, 3.4.2.2).
        uint16_t final_mtu = std::max(
            att::kLEMinMTU, std::min(server_mtu, att_->preferred_mtu()));
        att_->set_mtu(final_mtu);

        mtu_cb(fit::ok(final_mtu));
        return;
      }
      const auto& [error, handle] = result.error_value();

      // "If the Error Response is sent by the server with the Error Code
      // set to Request Not Supported, [...] the default MTU shall be used
      // (Vol 3, Part G, 4.3.1)"
      if (error.is(att::ErrorCode::kRequestNotSupported)) {
        bt_log(
            DEBUG, "gatt", "peer does not support MTU exchange: using default");
        att_->set_mtu(att::kLEMinMTU);
        mtu_cb(fit::error(error));
        return;
      }

      bt_log(DEBUG, "gatt", "MTU exchange failed: %s", bt_str(error));
      mtu_cb(fit::error(error));
    };

    att_->StartTransaction(std::move(pdu), BindCallback(std::move(rsp_cb)));
  }

  void DiscoverServices(ServiceKind kind,
                        ServiceCallback svc_callback,
                        att::ResultFunction<> status_callback) override {
    DiscoverServicesInRange(kind,
                            att::kHandleMin,
                            att::kHandleMax,
                            std::move(svc_callback),
                            std::move(status_callback));
  }

  void DiscoverServicesInRange(ServiceKind kind,
                               att::Handle range_start,
                               att::Handle range_end,
                               ServiceCallback svc_callback,
                               att::ResultFunction<> status_callback) override {
    BT_ASSERT(range_start <= range_end);

    auto pdu = NewPDU(sizeof(att::ReadByGroupTypeRequestParams16));
    if (!pdu) {
      status_callback(ToResult(HostError::kOutOfMemory));
      return;
    }

    att::PacketWriter writer(att::kReadByGroupTypeRequest, pdu.get());
    auto* params =
        writer.mutable_payload<att::ReadByGroupTypeRequestParams16>();
    params->start_handle = htole16(range_start);
    params->end_handle = htole16(range_end);
    params->type =
        htole16(kind == ServiceKind::PRIMARY ? types::kPrimaryService16
                                             : types::kSecondaryService16);

    auto rsp_cb = [this,
                   kind,
                   range_start,
                   range_end,
                   svc_cb = std::move(svc_callback),
                   res_cb = std::move(status_callback)](
                      att::Bearer::TransactionResult result) mutable {
      if (result.is_error()) {
        const att::Error& error = result.error_value().first;

        // An Error Response code of "Attribute Not Found" indicates the end of
        // the procedure (v5.0, Vol 3, Part G, 4.4.1).
        if (error.is(att::ErrorCode::kAttributeNotFound)) {
          res_cb(fit::ok());
          return;
        }

        res_cb(fit::error(error));
        return;
      }

      const att::PacketReader& rsp = result.value();
      BT_DEBUG_ASSERT(rsp.opcode() == att::kReadByGroupTypeResponse);
      TRACE_DURATION("bluetooth",
                     "gatt::Client::DiscoverServicesInRange rsp_cb",
                     "size",
                     rsp.size());

      if (rsp.payload_size() < sizeof(att::ReadByGroupTypeResponseParams)) {
        // Received malformed response. Disconnect the link.
        bt_log(DEBUG, "gatt", "received malformed Read By Group Type response");
        att_->ShutDown();
        res_cb(ToResult(HostError::kPacketMalformed));
        return;
      }

      const auto& rsp_params =
          rsp.payload<att::ReadByGroupTypeResponseParams>();
      uint8_t entry_length = rsp_params.length;

      // We expect the returned attribute value to be a 16-bit or 128-bit
      // service UUID.
      constexpr size_t kAttrDataSize16 =
          sizeof(att::AttributeGroupDataEntry) + sizeof(att::AttributeType16);
      constexpr size_t kAttrDataSize128 =
          sizeof(att::AttributeGroupDataEntry) + sizeof(att::AttributeType128);

      if (entry_length != kAttrDataSize16 && entry_length != kAttrDataSize128) {
        bt_log(DEBUG, "gatt", "invalid attribute data length");
        att_->ShutDown();
        res_cb(ToResult(HostError::kPacketMalformed));
        return;
      }

      BufferView attr_data_list(rsp_params.attribute_data_list,
                                rsp.payload_size() - 1);
      if (attr_data_list.size() % entry_length) {
        bt_log(DEBUG, "gatt", "malformed attribute data list");
        att_->ShutDown();
        res_cb(ToResult(HostError::kPacketMalformed));
        return;
      }

      std::optional<att::Handle> last_handle;
      while (attr_data_list.size()) {
        att::Handle start = le16toh(
            attr_data_list
                .ReadMember<&att::AttributeGroupDataEntry::start_handle>());
        att::Handle end = le16toh(
            attr_data_list
                .ReadMember<&att::AttributeGroupDataEntry::group_end_handle>());

        if (end < start) {
          bt_log(DEBUG, "gatt", "received malformed service range values");
          res_cb(ToResult(HostError::kPacketMalformed));
          return;
        }

        if (start < range_start || start > range_end) {
          bt_log(DEBUG,
                 "gatt",
                 "received service range values outside of requested range");
          res_cb(ToResult(HostError::kPacketMalformed));
          return;
        }

        // "The Attribute Data List is ordered sequentially based on the
        // attribute handles." (Core Spec v5.3, Vol 3, Part F, Sec 3.4.4.10)
        if (last_handle.has_value() && start <= last_handle.value()) {
          bt_log(DEBUG, "gatt", "received services out of order");
          res_cb(ToResult(HostError::kPacketMalformed));
          return;
        }

        // This must succeed as we have performed the appropriate checks above.
        auto uuid_bytes =
            attr_data_list.view(offsetof(att::AttributeGroupDataEntry, value),
                                entry_length - (2 * sizeof(att::Handle)));
        UUID uuid(uuid_bytes);

        ServiceData service(kind, start, end, uuid);
        last_handle = service.range_end;

        // Notify the handler.
        svc_cb(service);

        attr_data_list = attr_data_list.view(entry_length);
      }

      // The procedure is over if we have reached the end of the handle range.
      if (!last_handle.has_value() || last_handle.value() == range_end) {
        res_cb(fit::ok());
        return;
      }

      // Request the next batch.
      DiscoverServicesInRange(kind,
                              last_handle.value() + 1,
                              range_end,
                              std::move(svc_cb),
                              std::move(res_cb));
    };

    att_->StartTransaction(std::move(pdu), BindCallback(std::move(rsp_cb)));
  }

  void DiscoverServicesWithUuids(ServiceKind kind,
                                 ServiceCallback svc_cb,
                                 att::ResultFunction<> status_cb,
                                 std::vector<UUID> uuids) override {
    DiscoverServicesWithUuidsInRange(kind,
                                     att::kHandleMin,
                                     att::kHandleMax,
                                     std::move(svc_cb),
                                     std::move(status_cb),
                                     std::move(uuids));
  }

  void DiscoverServicesWithUuidsInRange(ServiceKind kind,
                                        att::Handle range_start,
                                        att::Handle range_end,
                                        ServiceCallback svc_callback,
                                        att::ResultFunction<> status_callback,
                                        std::vector<UUID> uuids) override {
    BT_ASSERT(range_start <= range_end);
    BT_ASSERT(!uuids.empty());
    UUID uuid = uuids.back();
    uuids.pop_back();

    auto recursive_status_cb = [this,
                                range_start,
                                range_end,
                                kind,
                                svc_cb = svc_callback.share(),
                                status_cb = std::move(status_callback),
                                remaining_uuids =
                                    std::move(uuids)](auto status) mutable {
      // Base case
      if (status.is_error() || remaining_uuids.empty()) {
        status_cb(status);
        return;
      }

      // Recursively discover with the remaining UUIDs.
      DiscoverServicesWithUuidsInRange(kind,
                                       range_start,
                                       range_end,
                                       std::move(svc_cb),
                                       std::move(status_cb),
                                       std::move(remaining_uuids));
    };

    // Discover the last uuid in uuids.
    DiscoverServicesByUuidInRange(kind,
                                  range_start,
                                  range_end,
                                  std::move(svc_callback),
                                  std::move(recursive_status_cb),
                                  uuid);
  }

  void DiscoverServicesByUuidInRange(ServiceKind kind,
                                     att::Handle start,
                                     att::Handle end,
                                     ServiceCallback svc_callback,
                                     att::ResultFunction<> status_callback,
                                     UUID uuid) {
    size_t uuid_size_bytes = uuid.CompactSize(/* allow 32 bit UUIDs */ false);
    auto pdu =
        NewPDU(sizeof(att::FindByTypeValueRequestParams) + uuid_size_bytes);
    if (!pdu) {
      status_callback(ToResult(HostError::kOutOfMemory));
      return;
    }

    att::PacketWriter writer(att::kFindByTypeValueRequest, pdu.get());
    auto* params = writer.mutable_payload<att::FindByTypeValueRequestParams>();
    params->start_handle = htole16(start);
    params->end_handle = htole16(end);
    params->type =
        htole16(kind == ServiceKind::PRIMARY ? types::kPrimaryService16
                                             : types::kSecondaryService16);
    MutableBufferView value_view(params->value, uuid_size_bytes);
    uuid.ToBytes(&value_view, /* allow 32 bit UUIDs */ false);

    auto rsp_cb = [this,
                   kind,
                   discovery_range_start = start,
                   discovery_range_end = end,
                   svc_cb = std::move(svc_callback),
                   res_cb = std::move(status_callback),
                   uuid](att::Bearer::TransactionResult result) mutable {
      if (result.is_error()) {
        const att::Error& error = result.error_value().first;

        // An Error Response code of "Attribute Not Found" indicates the end of
        // the procedure (v5.0, Vol 3, Part G, 4.4.2).
        if (error.is(att::ErrorCode::kAttributeNotFound)) {
          res_cb(fit::ok());
          return;
        }

        res_cb(fit::error(error));
        return;
      }

      const att::PacketReader& rsp = result.value();
      BT_DEBUG_ASSERT(rsp.opcode() == att::kFindByTypeValueResponse);

      size_t payload_size = rsp.payload_size();
      if (payload_size < 1 ||
          payload_size % sizeof(att::FindByTypeValueResponseParams) != 0) {
        // Received malformed response. Disconnect the link.
        bt_log(DEBUG,
               "gatt",
               "received malformed Find By Type Value response with size %zu",
               payload_size);
        att_->ShutDown();
        res_cb(ToResult(HostError::kPacketMalformed));
        return;
      }

      BufferView handle_list = rsp.payload_data();

      std::optional<att::Handle> last_handle;
      while (handle_list.size()) {
        const auto& entry = handle_list.To<att::HandlesInformationList>();

        att::Handle start = le16toh(entry.handle);
        att::Handle end = le16toh(entry.group_end_handle);

        if (end < start) {
          bt_log(DEBUG, "gatt", "received malformed service range values");
          res_cb(ToResult(HostError::kPacketMalformed));
          return;
        }

        if (start < discovery_range_start || start > discovery_range_end) {
          bt_log(DEBUG,
                 "gatt",
                 "received service range values outside of requested range");
          res_cb(ToResult(HostError::kPacketMalformed));
          return;
        }

        // "The Handles Information List is ordered sequentially based on the
        // found attribute handles." (Core Spec v5.3, Vol 3, Part F,
        // Sec 3.4.3.4)
        if (last_handle.has_value() && start <= last_handle.value()) {
          bt_log(DEBUG, "gatt", "received services out of order");
          res_cb(ToResult(HostError::kPacketMalformed));
          return;
        }

        ServiceData service(kind, start, end, uuid);

        // Notify the handler.
        svc_cb(service);

        // HandlesInformationList is a single element of the list.
        size_t entry_length = sizeof(att::HandlesInformationList);
        handle_list = handle_list.view(entry_length);

        last_handle = service.range_end;
      }

      // The procedure is over if we have reached the end of the handle range.
      if (!last_handle.has_value() ||
          last_handle.value() == discovery_range_end) {
        res_cb(fit::ok());
        return;
      }

      // Request the next batch.
      DiscoverServicesByUuidInRange(kind,
                                    last_handle.value() + 1,
                                    discovery_range_end,
                                    std::move(svc_cb),
                                    std::move(res_cb),
                                    uuid);
    };

    att_->StartTransaction(std::move(pdu), BindCallback(std::move(rsp_cb)));
  }

  void DiscoverCharacteristics(att::Handle range_start,
                               att::Handle range_end,
                               CharacteristicCallback chrc_callback,
                               att::ResultFunction<> status_callback) override {
    BT_ASSERT(range_start <= range_end);
    BT_ASSERT(chrc_callback);
    BT_ASSERT(status_callback);

    if (range_start == range_end) {
      status_callback(fit::ok());
      return;
    }

    auto read_by_type_cb = [this,
                            range_end,
                            chrc_cb = std::move(chrc_callback),
                            res_cb = status_callback.share()](
                               ReadByTypeResult result) mutable {
      TRACE_DURATION("bluetooth",
                     "gatt::Client::DiscoverCharacteristics read_by_type_cb");

      if (result.is_error()) {
        const auto error = result.error_value().error;

        // An Error Response code of "Attribute Not Found" indicates the end
        // of the procedure (v5.0, Vol 3, Part G, 4.6.1).
        if (error.is(att::ErrorCode::kAttributeNotFound)) {
          res_cb(fit::ok());
          return;
        }

        res_cb(fit::error(error));
        return;
      }

      auto& attributes = result.value();

      // ReadByTypeRequest() should return an error result if there are no
      // attributes in a success response.
      BT_ASSERT(!attributes.empty());

      for (auto& char_attr : attributes) {
        Properties properties = 0u;
        att::Handle value_handle = 0u;
        UUID value_uuid;

        // The characteristic declaration value contains:
        // 1 octet: properties
        // 2 octets: value handle
        // 2 or 16 octets: UUID
        if (char_attr.value.size() ==
            sizeof(CharacteristicDeclarationAttributeValue<
                   att::UUIDType::k16Bit>)) {
          auto attr_value = char_attr.value.To<
              CharacteristicDeclarationAttributeValue<att::UUIDType::k16Bit>>();
          properties = attr_value.properties;
          value_handle = le16toh(attr_value.value_handle);
          value_uuid = UUID(attr_value.value_uuid);
        } else if (char_attr.value.size() ==
                   sizeof(CharacteristicDeclarationAttributeValue<
                          att::UUIDType::k128Bit>)) {
          auto attr_value =
              char_attr.value.To<CharacteristicDeclarationAttributeValue<
                  att::UUIDType::k128Bit>>();
          properties = attr_value.properties;
          value_handle = le16toh(attr_value.value_handle);
          value_uuid = UUID(attr_value.value_uuid);
        } else {
          bt_log(DEBUG,
                 "gatt",
                 "invalid characteristic declaration attribute value size");
          att_->ShutDown();
          res_cb(ToResult(HostError::kPacketMalformed));
          return;
        }

        // Vol 3, Part G, 3.3: "The Characteristic Value declaration shall
        // exist immediately following the characteristic declaration."
        if (value_handle != char_attr.handle + 1) {
          bt_log(
              DEBUG, "gatt", "characteristic value doesn't follow declaration");
          res_cb(ToResult(HostError::kPacketMalformed));
          return;
        }

        // Notify the handler. By default, there are no extended properties to
        // report.
        chrc_cb(CharacteristicData(properties,
                                   /*ext_props=*/std::nullopt,
                                   char_attr.handle,
                                   value_handle,
                                   value_uuid));
      }

      // The procedure is over if we have reached the end of the handle
      // range.
      const auto last_handle = attributes.back().handle;
      if (last_handle == range_end) {
        res_cb(fit::ok());
        return;
      }

      // Request the next batch.
      DiscoverCharacteristics(
          last_handle + 1, range_end, std::move(chrc_cb), std::move(res_cb));
    };

    ReadByTypeRequest(types::kCharacteristicDeclaration,
                      range_start,
                      range_end,
                      std::move(read_by_type_cb));
  }

  void DiscoverDescriptors(att::Handle range_start,
                           att::Handle range_end,
                           DescriptorCallback desc_callback,
                           att::ResultFunction<> status_callback) override {
    BT_DEBUG_ASSERT(range_start <= range_end);
    BT_DEBUG_ASSERT(desc_callback);
    BT_DEBUG_ASSERT(status_callback);

    auto pdu = NewPDU(sizeof(att::FindInformationRequestParams));
    if (!pdu) {
      status_callback(ToResult(HostError::kOutOfMemory));
      return;
    }

    att::PacketWriter writer(att::kFindInformationRequest, pdu.get());
    auto* params = writer.mutable_payload<att::FindInformationRequestParams>();
    params->start_handle = htole16(range_start);
    params->end_handle = htole16(range_end);

    auto rsp_cb = [this,
                   range_start,
                   range_end,
                   desc_cb = std::move(desc_callback),
                   res_cb = std::move(status_callback)](
                      att::Bearer::TransactionResult result) mutable {
      if (result.is_error()) {
        const att::Error& error = result.error_value().first;

        // An Error Response code of "Attribute Not Found" indicates the end of
        // the procedure (v5.0, Vol 3, Part G, 4.7.1).
        if (error.is(att::ErrorCode::kAttributeNotFound)) {
          res_cb(fit::ok());
          return;
        }

        res_cb(fit::error(error));
        return;
      }
      const att::PacketReader& rsp = result.value();
      BT_DEBUG_ASSERT(rsp.opcode() == att::kFindInformationResponse);
      TRACE_DURATION("bluetooth",
                     "gatt::Client::DiscoverDescriptors rsp_cb",
                     "size",
                     rsp.size());

      if (rsp.payload_size() < sizeof(att::FindInformationResponseParams)) {
        bt_log(DEBUG, "gatt", "received malformed Find Information response");
        att_->ShutDown();
        res_cb(ToResult(HostError::kPacketMalformed));
        return;
      }

      const auto& rsp_params =
          rsp.payload<att::FindInformationResponseParams>();
      BufferView entries = rsp.payload_data().view(sizeof(rsp_params.format));

      att::Handle last_handle;
      bool well_formed;
      switch (rsp_params.format) {
        case att::UUIDType::k16Bit:
          well_formed =
              ProcessDescriptorDiscoveryResponse<att::UUIDType::k16Bit>(
                  range_start,
                  range_end,
                  entries,
                  desc_cb.share(),
                  &last_handle);
          break;
        case att::UUIDType::k128Bit:
          well_formed =
              ProcessDescriptorDiscoveryResponse<att::UUIDType::k128Bit>(
                  range_start,
                  range_end,
                  entries,
                  desc_cb.share(),
                  &last_handle);
          break;
        default:
          bt_log(DEBUG, "gatt", "invalid information data format");
          well_formed = false;
          break;
      }

      if (!well_formed) {
        att_->ShutDown();
        res_cb(ToResult(HostError::kPacketMalformed));
        return;
      }

      // The procedure is over if we have reached the end of the handle range.
      if (last_handle == range_end) {
        res_cb(fit::ok());
        return;
      }

      // Request the next batch.
      DiscoverDescriptors(
          last_handle + 1, range_end, std::move(desc_cb), std::move(res_cb));
    };

    att_->StartTransaction(std::move(pdu), BindCallback(std::move(rsp_cb)));
  }

  void ReadRequest(att::Handle handle, ReadCallback callback) override {
    auto pdu = NewPDU(sizeof(att::ReadRequestParams));
    if (!pdu) {
      callback(ToResult(HostError::kOutOfMemory),
               BufferView(),
               /*maybe_truncated=*/false);
      return;
    }

    att::PacketWriter writer(att::kReadRequest, pdu.get());
    auto params = writer.mutable_payload<att::ReadRequestParams>();
    params->handle = htole16(handle);

    auto rsp_cb = [this, callback = std::move(callback)](
                      att::Bearer::TransactionResult result) {
      if (result.is_ok()) {
        const att::PacketReader& rsp = result.value();
        BT_DEBUG_ASSERT(rsp.opcode() == att::kReadResponse);
        bool maybe_truncated =
            (rsp.payload_size() != att::kMaxAttributeValueLength) &&
            (rsp.payload_size() == (mtu() - sizeof(rsp.opcode())));
        callback(fit::ok(), rsp.payload_data(), maybe_truncated);
        return;
      }
      const auto& [error, handle] = result.error_value();
      bt_log(DEBUG,
             "gatt",
             "read request failed: %s, handle %#.4x",
             bt_str(error),
             handle);
      callback(fit::error(error), BufferView(), /*maybe_truncated=*/false);
    };

    att_->StartTransaction(std::move(pdu), BindCallback(std::move(rsp_cb)));
  }

  void ReadByTypeRequest(const UUID& type,
                         att::Handle start_handle,
                         att::Handle end_handle,
                         ReadByTypeCallback callback) override {
    size_t type_size = type.CompactSize(/*allow_32bit=*/false);
    BT_ASSERT(type_size == sizeof(uint16_t) || type_size == sizeof(UInt128));
    auto pdu = NewPDU(type_size == sizeof(uint16_t)
                          ? sizeof(att::ReadByTypeRequestParams16)
                          : sizeof(att::ReadByTypeRequestParams128));
    if (!pdu) {
      callback(fit::error(
          ReadByTypeError{Error(HostError::kOutOfMemory), std::nullopt}));
      return;
    }

    att::PacketWriter writer(att::kReadByTypeRequest, pdu.get());
    if (type_size == sizeof(uint16_t)) {
      auto params = writer.mutable_payload<att::ReadByTypeRequestParams16>();
      params->start_handle = htole16(start_handle);
      params->end_handle = htole16(end_handle);
      auto type_view = MutableBufferView(&params->type, sizeof(params->type));
      type.ToBytes(&type_view, /*allow_32bit=*/false);
    } else {
      auto params = writer.mutable_payload<att::ReadByTypeRequestParams128>();
      params->start_handle = htole16(start_handle);
      params->end_handle = htole16(end_handle);
      auto type_view = MutableBufferView(&params->type, sizeof(params->type));
      type.ToBytes(&type_view, /*allow_32bit=*/false);
    }

    auto rsp_cb = [this,
                   callback = std::move(callback),
                   start_handle,
                   end_handle](att::Bearer::TransactionResult result) {
      if (result.is_error()) {
        const auto& [error, handle] = result.error_value();
        bt_log(DEBUG,
               "gatt",
               "read by type request failed: %s, handle %#.4x",
               bt_str(error),
               handle);
        // Only some errors have handles.
        std::optional<att::Handle> cb_handle =
            handle ? std::optional(handle) : std::nullopt;
        callback(fit::error(ReadByTypeError{error, cb_handle}));
        return;
      }
      const att::PacketReader& rsp = result.value();
      BT_ASSERT(rsp.opcode() == att::kReadByTypeResponse);
      if (rsp.payload_size() < sizeof(att::ReadByTypeResponseParams)) {
        callback(fit::error(
            ReadByTypeError{Error(HostError::kPacketMalformed), std::nullopt}));
        return;
      }

      const auto& params = rsp.payload<att::ReadByTypeResponseParams>();
      // The response contains a list of attribute handle-value pairs of uniform
      // length.
      const size_t list_size = rsp.payload_size() - sizeof(params.length);
      const size_t pair_size = params.length;

      // Success response must:
      // a) Specify valid pair length (at least the size of a handle).
      // b) Have at least 1 pair (otherwise the Attribute Not Found error should
      // have been
      //    sent).
      // c) Have a list size that is evenly divisible by pair size.
      if (pair_size < sizeof(att::Handle) || list_size < sizeof(att::Handle) ||
          list_size % pair_size != 0) {
        callback(fit::error(
            ReadByTypeError{Error(HostError::kPacketMalformed), std::nullopt}));
        return;
      }

      std::vector<ReadByTypeValue> attributes;
      BufferView attr_list_view(params.attribute_data_list,
                                rsp.payload_size() - sizeof(params.length));
      while (attr_list_view.size() >= params.length) {
        const BufferView pair_view = attr_list_view.view(0, pair_size);
        const att::Handle handle = le16toh(pair_view.To<att::Handle>());

        if (handle < start_handle || handle > end_handle) {
          bt_log(TRACE,
                 "gatt",
                 "client received read by type response with handle outside of "
                 "requested range");
          callback(fit::error(ReadByTypeError{
              Error(HostError::kPacketMalformed), std::nullopt}));
          return;
        }

        if (!attributes.empty() && attributes.back().handle >= handle) {
          bt_log(TRACE,
                 "gatt",
                 "client received read by type response with handles in "
                 "non-increasing order");
          callback(fit::error(ReadByTypeError{
              Error(HostError::kPacketMalformed), std::nullopt}));
          return;
        }

        auto value_view = pair_view.view(sizeof(att::Handle));

        // The value may be truncated if it maxes out the length parameter or
        // the MTU, whichever is smaller (Core Spec v5.2, Vol 3, Part F,
        // Sec 3.4.4).
        const size_t mtu_max_value_size =
            mtu() - sizeof(att::kReadByTypeResponse) -
            sizeof(att::ReadByTypeResponseParams) - sizeof(att::Handle);
        bool maybe_truncated =
            (value_view.size() ==
             std::min(static_cast<size_t>(att::kMaxReadByTypeValueLength),
                      mtu_max_value_size));

        attributes.push_back(
            ReadByTypeValue{handle, value_view, maybe_truncated});

        // Advance list view to next pair (or end of list).
        attr_list_view = attr_list_view.view(pair_size);
      }
      BT_ASSERT(attr_list_view.size() == 0);

      callback(fit::ok(std::move(attributes)));
    };

    att_->StartTransaction(std::move(pdu), BindCallback(std::move(rsp_cb)));
  }

  void ReadBlobRequest(att::Handle handle,
                       uint16_t offset,
                       ReadCallback callback) override {
    auto pdu = NewPDU(sizeof(att::ReadBlobRequestParams));
    if (!pdu) {
      callback(ToResult(HostError::kOutOfMemory),
               BufferView(),
               /*maybe_truncated=*/false);
      return;
    }

    att::PacketWriter writer(att::kReadBlobRequest, pdu.get());
    auto params = writer.mutable_payload<att::ReadBlobRequestParams>();
    params->handle = htole16(handle);
    params->offset = htole16(offset);

    auto rsp_cb = [this, offset, callback = std::move(callback)](
                      att::Bearer::TransactionResult result) {
      if (result.is_ok()) {
        const att::PacketReader& rsp = result.value();
        BT_DEBUG_ASSERT(rsp.opcode() == att::kReadBlobResponse);
        bool maybe_truncated =
            (static_cast<size_t>(offset) + rsp.payload_size() !=
             att::kMaxAttributeValueLength) &&
            (rsp.payload_data().size() == (mtu() - sizeof(att::OpCode)));
        callback(fit::ok(), rsp.payload_data(), maybe_truncated);
        return;
      }
      const auto& [error, handle] = result.error_value();
      bt_log(DEBUG,
             "gatt",
             "read blob request failed: %s, handle: %#.4x",
             bt_str(error),
             handle);
      callback(fit::error(error), BufferView(), /*maybe_truncated=*/false);
    };

    att_->StartTransaction(std::move(pdu), BindCallback(std::move(rsp_cb)));
  }

  void WriteRequest(att::Handle handle,
                    const ByteBuffer& value,
                    att::ResultFunction<> callback) override {
    const size_t payload_size = sizeof(att::WriteRequestParams) + value.size();
    if (sizeof(att::OpCode) + payload_size > att_->mtu()) {
      bt_log(TRACE, "gatt", "write request payload exceeds MTU");
      callback(ToResult(HostError::kPacketMalformed));
      return;
    }

    auto pdu = NewPDU(payload_size);
    if (!pdu) {
      callback(ToResult(HostError::kOutOfMemory));
      return;
    }

    att::PacketWriter writer(att::kWriteRequest, pdu.get());
    auto params = writer.mutable_payload<att::WriteRequestParams>();
    params->handle = htole16(handle);

    auto value_view =
        writer.mutable_payload_data().mutable_view(sizeof(att::Handle));
    value.Copy(&value_view);

    auto rsp_cb = [this, callback = std::move(callback)](
                      att::Bearer::TransactionResult result) {
      if (result.is_error()) {
        const auto& [error, handle] = result.error_value();
        bt_log(DEBUG,
               "gatt",
               "write request failed: %s, handle: %#.2x",
               bt_str(error),
               handle);
        callback(fit::error(error));
        return;
      }
      const att::PacketReader& rsp = result.value();
      BT_DEBUG_ASSERT(rsp.opcode() == att::kWriteResponse);

      if (rsp.payload_size()) {
        att_->ShutDown();
        callback(ToResult(HostError::kPacketMalformed));
        return;
      }

      callback(fit::ok());
    };

    att_->StartTransaction(std::move(pdu), BindCallback(std::move(rsp_cb)));
  }

  // An internal object for storing the write queue, callback, and reliability
  // mode of a long write operation.
  struct PreparedWrite {
    bt::att::PrepareWriteQueue prep_write_queue;
    bt::att::ResultFunction<> callback;
    ReliableMode reliable_mode;
  };

  void ExecutePrepareWrites(att::PrepareWriteQueue prep_write_queue,
                            ReliableMode reliable_mode,
                            att::ResultFunction<> callback) override {
    PreparedWrite new_request;
    new_request.prep_write_queue = std::move(prep_write_queue);
    new_request.callback = std::move(callback);
    new_request.reliable_mode = std::move(reliable_mode);
    long_write_queue_.push(std::move(new_request));

    // If the |long_write_queue| has a pending request, then appending this
    // request will be sufficient, otherwise kick off the request.
    if (long_write_queue_.size() == 1) {
      ProcessWriteQueue(std::move(long_write_queue_.front()));
    }
  }

  void ProcessWriteQueue(PreparedWrite prep_write) {
    if (!prep_write.prep_write_queue.empty()) {
      att::QueuedWrite prep_write_request =
          std::move(prep_write.prep_write_queue.front());
      // A copy of the |prep_write_request| is made to pass into the capture
      // list for |prep_write_cb|. It will be used to validate the echoed blob.
      auto prep_write_copy = att::QueuedWrite(prep_write_request.handle(),
                                              prep_write_request.offset(),
                                              prep_write_request.value());
      prep_write.prep_write_queue.pop();

      auto prep_write_cb = [this,
                            prep_write = std::move(prep_write),
                            requested_blob = std::move(prep_write_copy)](
                               att::Result<> status,
                               const ByteBuffer& blob) mutable {
        // If the write fails, cancel the prep writes and then move on to the
        // next long write in the queue. The device will echo the value written
        // in the blob, according to the spec (Vol 3, Part G, 4.9.4). The offset
        // and value will be verified if the requested |prep_write.mode| is
        // enabled (Vol 3, Part G, 4.9.5).

        if (prep_write.reliable_mode == ReliableMode::kEnabled) {
          if (blob.size() < sizeof(att::PrepareWriteResponseParams)) {
            // The response blob is malformed.
            status = ToResult(HostError::kNotReliable);
          } else {
            auto blob_offset = le16toh(
                blob.ReadMember<&att::PrepareWriteResponseParams::offset>());
            auto blob_value =
                blob.view(sizeof(att::PrepareWriteResponseParams));
            if ((blob_offset != requested_blob.offset()) ||
                !(blob_value == requested_blob.value())) {
              status = ToResult(HostError::kNotReliable);
            }
          }
        }

        if (status.is_error()) {
          auto exec_write_cb = [this,
                                callback = std::move(prep_write.callback),
                                prep_write_status =
                                    status](att::Result<> status) mutable {
            // In this case return the original failure status. This effectively
            // overrides the ExecuteWrite status.
            callback(prep_write_status);
            // Now that this request is complete, remove it from the overall
            // queue.
            BT_DEBUG_ASSERT(!long_write_queue_.empty());
            long_write_queue_.pop();

            if (long_write_queue_.size() > 0) {
              ProcessWriteQueue(std::move(long_write_queue_.front()));
            }
          };

          ExecuteWriteRequest(att::ExecuteWriteFlag::kCancelAll,
                              std::move(exec_write_cb));

          return;
        }

        ProcessWriteQueue(std::move(prep_write));
      };

      PrepareWriteRequest(prep_write_request.handle(),
                          prep_write_request.offset(),
                          std::move(prep_write_request.value()),
                          std::move(prep_write_cb));
    }
    // End of this write, send and prepare for next item in overall write queue
    else {
      auto exec_write_cb = [this, callback = std::move(prep_write.callback)](
                               att::Result<> status) mutable {
        callback(status);
        // Now that this request is complete, remove it from the overall
        // queue.
        BT_DEBUG_ASSERT(!long_write_queue_.empty());
        long_write_queue_.pop();

        // If the super queue still has any long writes left to execute,
        // initiate them
        if (long_write_queue_.size() > 0) {
          ProcessWriteQueue(std::move(long_write_queue_.front()));
        }
      };

      ExecuteWriteRequest(att::ExecuteWriteFlag::kWritePending,
                          std::move(exec_write_cb));
    }
  }

  void PrepareWriteRequest(att::Handle handle,
                           uint16_t offset,
                           const ByteBuffer& part_value,
                           PrepareCallback callback) override {
    const size_t payload_size =
        sizeof(att::PrepareWriteRequestParams) + part_value.size();
    if (sizeof(att::OpCode) + payload_size > att_->mtu()) {
      bt_log(TRACE, "gatt", "prepare write request payload exceeds MTU");
      callback(ToResult(HostError::kPacketMalformed), BufferView());
      return;
    }

    auto pdu = NewPDU(payload_size);
    if (!pdu) {
      callback(ToResult(HostError::kOutOfMemory), BufferView());
      return;
    }

    att::PacketWriter writer(att::kPrepareWriteRequest, pdu.get());
    auto params = writer.mutable_payload<att::PrepareWriteRequestParams>();
    params->handle = htole16(handle);
    params->offset = htole16(offset);

    auto header_size = sizeof(att::Handle) + sizeof(uint16_t);
    auto value_view = writer.mutable_payload_data().mutable_view(header_size);
    part_value.Copy(&value_view);

    auto rsp_cb = [callback = std::move(callback)](
                      att::Bearer::TransactionResult result) {
      if (result.is_ok()) {
        const att::PacketReader& rsp = result.value();
        BT_DEBUG_ASSERT(rsp.opcode() == att::kPrepareWriteResponse);
        callback(fit::ok(), rsp.payload_data());
        return;
      }
      const auto& [error, handle] = result.error_value();
      bt_log(DEBUG,
             "gatt",
             "prepare write request failed: %s, handle:"
             "%#.4x",
             bt_str(error),
             handle);
      callback(fit::error(error), BufferView());
    };

    att_->StartTransaction(std::move(pdu), BindCallback(std::move(rsp_cb)));
  }

  void ExecuteWriteRequest(att::ExecuteWriteFlag flag,
                           att::ResultFunction<> callback) override {
    const size_t payload_size = sizeof(att::ExecuteWriteRequestParams);
    if (sizeof(att::OpCode) + payload_size > att_->mtu()) {
      // This really shouldn't happen because we aren't consuming any actual
      // payload here, but just in case...
      bt_log(TRACE, "gatt", "execute write request size exceeds MTU");
      callback(ToResult(HostError::kPacketMalformed));
      return;
    }

    auto pdu = NewPDU(payload_size);
    if (!pdu) {
      callback(ToResult(HostError::kOutOfMemory));
      return;
    }

    att::PacketWriter writer(att::kExecuteWriteRequest, pdu.get());
    auto params = writer.mutable_payload<att::ExecuteWriteRequestParams>();
    params->flags = flag;

    auto rsp_cb = [this, callback = std::move(callback)](
                      att::Bearer::TransactionResult result) {
      if (result.is_ok()) {
        const att::PacketReader& rsp = result.value();
        BT_DEBUG_ASSERT(rsp.opcode() == att::kExecuteWriteResponse);

        if (rsp.payload_size()) {
          att_->ShutDown();
          callback(ToResult(HostError::kPacketMalformed));
          return;
        }

        callback(fit::ok());
        return;
      }
      const att::Error& error = result.error_value().first;
      bt_log(DEBUG, "gatt", "execute write request failed: %s", bt_str(error));
      callback(fit::error(error));
    };

    att_->StartTransaction(std::move(pdu), BindCallback(std::move(rsp_cb)));
  }

  void WriteWithoutResponse(att::Handle handle,
                            const ByteBuffer& value,
                            att::ResultFunction<> callback) override {
    const size_t payload_size = sizeof(att::WriteRequestParams) + value.size();
    if (sizeof(att::OpCode) + payload_size > att_->mtu()) {
      bt_log(DEBUG, "gatt", "write request payload exceeds MTU");
      callback(ToResult(HostError::kFailed));
      return;
    }

    auto pdu = NewPDU(payload_size);
    if (!pdu) {
      callback(ToResult(HostError::kOutOfMemory));
      return;
    }

    att::PacketWriter writer(att::kWriteCommand, pdu.get());
    auto params = writer.mutable_payload<att::WriteRequestParams>();
    params->handle = htole16(handle);

    auto value_view =
        writer.mutable_payload_data().mutable_view(sizeof(att::Handle));
    value.Copy(&value_view);

    [[maybe_unused]] bool _ = att_->SendWithoutResponse(std::move(pdu));
    callback(fit::ok());
  }

  void SetNotificationHandler(NotificationCallback handler) override {
    notification_handler_ = std::move(handler);
  }

  // Wraps |callback| in a TransactionCallback that only runs if this Client is
  // still alive.
  att::Bearer::TransactionCallback BindCallback(
      att::Bearer::TransactionCallback callback) {
    return [self = weak_self_.GetWeakPtr(),
            callback = std::move(callback)](auto rsp) mutable {
      if (self.is_alive()) {
        callback(rsp);
      }
    };
  }

  att::Bearer::WeakPtr att_;
  att::Bearer::HandlerId not_handler_id_;
  att::Bearer::HandlerId ind_handler_id_;

  NotificationCallback notification_handler_;
  // |long_write_queue_| contains long write requests, their
  // associated callbacks and reliable write modes.
  // Series of PrepareWrites are executed or cancelled at the same time so
  // this is used to block while a single series is processed.
  //
  // While the top element is processed, the |PrepareWriteQueue| and callback
  // will be empty and will be popped once the queue is cancelled or executed.
  // Following the processing of each queue, the client will automatically
  // process the next queue in the |long_write_queue_|.
  std::queue<PreparedWrite> long_write_queue_;
  WeakSelf<Client> weak_self_;

  BT_DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(Impl);
};

// static
std::unique_ptr<Client> Client::Create(att::Bearer::WeakPtr bearer) {
  return std::make_unique<Impl>(std::move(bearer));
}

}  // namespace bt::gatt
