// Copyright 2021 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_HCI_EXTENDED_LOW_ENERGY_ADVERTISER_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_HCI_EXTENDED_LOW_ENERGY_ADVERTISER_H_

#include "src/connectivity/bluetooth/core/bt-host/hci/advertising_handle_map.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/low_energy_advertiser.h"

namespace bt::hci {

class Transport;
class SequentialCommandRunner;

class ExtendedLowEnergyAdvertiser final : public LowEnergyAdvertiser {
 public:
  explicit ExtendedLowEnergyAdvertiser(fxl::WeakPtr<Transport> hci);
  ~ExtendedLowEnergyAdvertiser() override;

  bool AllowsRandomAddressChange() const override { return !IsAdvertising(); }

  // TODO(fxbug.dev/81470): The maximum length of data that can be advertised. For backwards
  // compatibility and because supporting it is a much larger project, we currently only support
  // legacy PDUs. When using legacy PDUs, the maximum advertising data size is
  // hci_spec::kMaxLEAdvertisingDataLength.
  //
  // TODO(fxbug.dev/77476): Extended advertising supports sending larger amounts of data, but they
  // have to be fragmented across multiple commands to the controller. This is not yet supported in
  // this implementation. We should support larger than kMaxLEExtendedAdvertisingDataLength
  // advertising data with fragmentation.
  size_t GetSizeLimit() const override { return hci_spec::kMaxLEAdvertisingDataLength; }

  // Attempt to start advertising. See LowEnergyAdvertiser::StartAdvertising for full documentation.
  //
  // According to the Bluetooth Spec, Volume 4, Part E, Section 7.8.58, "the number of advertising
  // sets that can be supported is not fixed and the Controller can change it at any time. The
  // memory used to store advertising sets can also be used for other purposes."
  //
  // This method may report an error if the controller cannot currently support another advertising
  // set.
  void StartAdvertising(const DeviceAddress& address, const AdvertisingData& data,
                        const AdvertisingData& scan_rsp, AdvertisingOptions adv_options,
                        ConnectionCallback connect_callback,
                        ResultFunction<> result_callback) override;

  void StopAdvertising() override;
  void StopAdvertising(const DeviceAddress& address) override;

  void OnIncomingConnection(hci_spec::ConnectionHandle handle, hci_spec::ConnectionRole role,
                            const DeviceAddress& peer_address,
                            const hci_spec::LEConnectionParameters& conn_params) override;

  size_t MaxAdvertisements() const override { return advertising_handle_map_.capacity(); }

  // Returns the last used advertising handle that was used for an advertising set when
  // communicating with the controller.
  std::optional<hci_spec::AdvertisingHandle> LastUsedHandleForTesting() const {
    return advertising_handle_map_.LastUsedHandleForTesting();
  }

 private:
  struct StagedConnectionParameters {
    hci_spec::ConnectionRole role;
    DeviceAddress peer_address;
    hci_spec::LEConnectionParameters conn_params;
  };

  struct StagedAdvertisingParameters {
    bool include_tx_power_level = false;
    int8_t selected_tx_power_level = 0;
  };

  std::unique_ptr<CommandPacket> BuildEnablePacket(const DeviceAddress& address,
                                                   hci_spec::GenericEnableParam enable) override;

  std::unique_ptr<CommandPacket> BuildSetAdvertisingParams(
      const DeviceAddress& address, hci_spec::LEAdvertisingType type,
      hci_spec::LEOwnAddressType own_address_type, AdvertisingIntervalRange interval) override;

  std::unique_ptr<CommandPacket> BuildSetAdvertisingData(const DeviceAddress& address,
                                                         const AdvertisingData& data,
                                                         AdvFlags flags) override;

  std::unique_ptr<CommandPacket> BuildUnsetAdvertisingData(const DeviceAddress& address) override;

  std::unique_ptr<CommandPacket> BuildSetScanResponse(const DeviceAddress& address,
                                                      const AdvertisingData& data) override;

  std::unique_ptr<CommandPacket> BuildUnsetScanResponse(const DeviceAddress& address) override;

  std::unique_ptr<CommandPacket> BuildRemoveAdvertisingSet(const DeviceAddress& address) override;

  void OnSetAdvertisingParamsComplete(const EventPacket& event) override;

  void OnCurrentOperationComplete() override;

  // Event handler for the HCI LE Advertising Set Terminated event
  CommandChannel::EventCallbackResult OnAdvertisingSetTerminatedEvent(const EventPacket& event);
  CommandChannel::EventHandlerId set_terminated_event_handler_id_;

  AdvertisingHandleMap advertising_handle_map_;
  std::queue<fit::closure> op_queue_;
  StagedAdvertisingParameters staged_advertising_parameters_;

  // Core Spec Volume 4, Part E, Section 7.8.56: Incoming connections to LE Extended Advertising
  // occur through two events: HCI_LE_Connection_Complete and HCI_LE_Advertising_Set_Terminated.
  // The HCI_LE_Connection_Complete event provides the connection handle along with some other
  // connection related parameters. Notably missing is the advertising handle, which we need to
  // obtain the advertised device address. Until we receive the HCI_LE_Advertising_Set_Terminated
  // event, we stage these parameters.
  std::unordered_map<hci_spec::ConnectionHandle, StagedConnectionParameters>
      staged_connections_map_;

  // Keep this as the last member to make sure that all weak pointers are invalidated before other
  // members get destroyed
  fxl::WeakPtrFactory<ExtendedLowEnergyAdvertiser> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ExtendedLowEnergyAdvertiser);
};

}  // namespace bt::hci

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_HCI_EXTENDED_LOW_ENERGY_ADVERTISER_H_
