// Copyright 2017 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_GAP_LOW_ENERGY_ADVERTISING_MANAGER_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_LOW_ENERGY_ADVERTISING_MANAGER_H_

#include <lib/fit/function.h>

#include "src/connectivity/bluetooth/core/bt-host/common/advertising_data.h"
#include "src/connectivity/bluetooth/core/bt-host/common/identifier.h"
#include "src/connectivity/bluetooth/core/bt-host/gap/gap.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/constants.h"
#include "src/connectivity/bluetooth/core/bt-host/hci/low_energy_advertiser.h"
#include "src/lib/fxl/memory/weak_ptr.h"

namespace bt {

namespace hci {
class Connection;
class LocalAddressDelegate;
class Transport;
}  // namespace hci

namespace gap {

using AdvertisementId = Identifier<uint64_t>;
constexpr AdvertisementId kInvalidAdvertisementId(0u);

class LowEnergyAdvertisingManager;

// Represents an active advertising instance. Stops the associated advertisement upon destruction.
class AdvertisementInstance final {
 public:
  // The default constructor initializes an instance with an invalid ID.
  AdvertisementInstance();
  ~AdvertisementInstance();

  AdvertisementInstance(AdvertisementInstance&& other) { Move(&other); }
  AdvertisementInstance& operator=(AdvertisementInstance&& other) {
    Move(&other);
    return *this;
  }

  AdvertisementId id() const { return id_; }

 private:
  friend class LowEnergyAdvertisingManager;

  AdvertisementInstance(AdvertisementId id, fxl::WeakPtr<LowEnergyAdvertisingManager> owner);
  void Move(AdvertisementInstance* other);
  void Reset();

  AdvertisementId id_;
  fxl::WeakPtr<LowEnergyAdvertisingManager> owner_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(AdvertisementInstance);
};

// Enum values for determining the advertising interval range. These ranges come from Core
// Specification v5.1, Vol 3, Part C, Appendix A (see also the constants defined in gap.h).
enum class AdvertisingInterval {
  FAST1,
  FAST2,
  SLOW,
};

class LowEnergyAdvertisingManager {
 public:
  LowEnergyAdvertisingManager(hci::LowEnergyAdvertiser* advertiser,
                              hci::LocalAddressDelegate* local_addr_delegate);
  virtual ~LowEnergyAdvertisingManager();

  // Returns true if the controller is currently advertising.
  bool advertising() const { return !advertisements_.empty(); }

  // Asynchronously attempts to start advertising a set of |data| with
  // additional scan response data |scan_rsp|.
  //
  // If |connect_callback| is provided, the advertisement will be connectable
  // and it will be called with the returned advertisement_id and a pointer to
  // the new connection, at which point the advertisement will have been
  // stopped.
  //
  // Returns false if the parameters represent an invalid advertisement:
  //  * if |anonymous| is true but |callback| is set
  //
  // |status_callback| may be called synchronously within this function.
  // |status_callback| provides one of:
  //  - an |advertisement_id|, which can be used to stop advertising
  //    or disambiguate calls to |callback|, and a success |status|.
  //  - kInvalidAdvertisementId and an error indication in |status|:
  //    * HostError::kInvalidParameters if the advertising parameters
  //      are invalid (e.g. |data| is too large).
  //    * HostError::kNotSupported if another set cannot be advertised
  //      or if the requested parameters are not supported by the hardware.
  //    * HostError::kProtocolError with a HCI error reported from
  //      the controller, otherwise.
  using ConnectionCallback =
      fit::function<void(AdvertisementId advertisement_id, std::unique_ptr<hci::Connection> link)>;
  using AdvertisingStatusCallback =
      fit::function<void(AdvertisementInstance instance, hci::Status status)>;
  void StartAdvertising(AdvertisingData data, AdvertisingData scan_rsp,
                        ConnectionCallback connect_callback, AdvertisingInterval interval,
                        bool anonymous, bool include_tx_power_level,
                        AdvertisingStatusCallback status_callback);

  // Stop advertising the advertisement with the id |advertisement_id|
  // Returns true if an advertisement was stopped, and false otherwise.
  // This function is idempotent.
  bool StopAdvertising(AdvertisementId advertisement_id);

 private:
  class ActiveAdvertisement;

  // Active advertisements, indexed by id.
  // TODO(armansito): Use fbl::HashMap here (fxbug.dev/652) or move
  // ActiveAdvertisement definition here and store by value (it is a small
  // object).
  std::unordered_map<AdvertisementId, std::unique_ptr<ActiveAdvertisement>> advertisements_;

  // Used to communicate with the controller. |advertiser_| must outlive this
  // advertising manager.
  hci::LowEnergyAdvertiser* advertiser_;  // weak

  // Used to obtain the local device address for advertising. Must outlive this
  // advertising manager.
  hci::LocalAddressDelegate* local_addr_delegate_;  // weak

  // Note: Should remain the last member so it'll be destroyed and
  // invalidate it's pointers before other members are destroyed.
  fxl::WeakPtrFactory<LowEnergyAdvertisingManager> weak_ptr_factory_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(LowEnergyAdvertisingManager);
};

}  // namespace gap
}  // namespace bt

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_LOW_ENERGY_ADVERTISING_MANAGER_H_
