// 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_DISCOVERY_FILTER_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_DISCOVERY_FILTER_H_

#include <string>
#include <vector>

#include "src/connectivity/bluetooth/core/bt-host/common/uuid.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/constants.h"

namespace bt {

class ByteBuffer;

namespace gap {

class Peer;

// A DiscoveryFilter allows clients of discovery procedures to filter results
// based on certain parameters, such as service UUIDs that might be present in
// EIR or advertising data, or based on available proximity information, to name
// a few.
class DiscoveryFilter final {
 public:
  DiscoveryFilter() = default;

  // Discovery filter based on the "Flags" bit field in LE Advertising Data. If
  // |require_all| is true, then The filter is considered satisifed if ALL of
  // the bits set in |flags_bitfield| are present in the advertisement.
  // Otherwise, the filter is considered satisfied as long as one of the bits
  // set in |flags_bitfield| is present.
  void set_flags(uint8_t flags_bitfield, bool require_all = false) {
    flags_ = flags_bitfield;
    all_flags_required_ = require_all;
  }

  // Discovery filter based on whether or not a device is connectable.
  void set_connectable(bool connectable) { connectable_ = connectable; }

  // Sets the service UUIDs that should be present in a scan result. A scan
  // result satisfies this filter if it provides at least one of the provided
  // UUIDs.
  //
  // Passing an empty value for |service_uuids| effectively disables this
  // filter.
  void set_service_uuids(const std::vector<UUID>& service_uuids) { service_uuids_ = service_uuids; }

  // Sets a string to be matched against the device name. A scan result
  // satisifes this filter if part of the complete or shortened device name
  // fields matches |name_substring|.
  //
  // Passing an empty value for |name_substring| effectively disables this
  // filter.
  void set_name_substring(const std::string& name_substring) { name_substring_ = name_substring; }

  // Sets a device to be filtered by the pathloss (in dBm) of the radio wave.
  // This value is calculated using the received signal strength (measured
  // locally) and the transmission power of the signal (as reported by the
  // remote):
  //
  //   Path Loss = RSSI - Tx Power
  //
  // If this filter parameter has been set and the pathloss value calculated for
  // a device greater than the provided |pathloss| value, then the scan result
  // will fail to satisfy this filter.
  //
  // If this filter parameter has been set and the pathloss value cannot be
  // calculated because the remote device did not report its transmission power,
  // then the device will fail to satisfy this filter UNLESS an RSSI filter
  // parameter has been set via SetRSSI() that is satisfied by the scan result.
  void set_pathloss(int8_t pathloss) { pathloss_ = pathloss; }

  // Sets a device to be filtered by RSSI. While this can produce inaccurate
  // results when used alone to approximate proximity, it can still be useful
  // when the scan results do not provide the remote device's Transmission
  // Power.
  //
  // A remote device is considered to satisfy this filter parameter if the RSSI
  // of the received transmission is greater than or equal to |rssi|, except if
  // a path loss filter was provided via SetPathLoss() which the remote device
  // failed to satisfy (see comments on SetPathLoss()).
  void set_rssi(int8_t rssi) { rssi_ = rssi; }

  // Sets a device to be filtered by manufacturer specific data. A scan result
  // satisfies this filter if it advertises manufacturer specific data
  // containing |manufacturer_code|.
  void set_manufacturer_code(uint16_t manufacturer_code) { manufacturer_code_ = manufacturer_code; }

  // Sets this filter up for the "General Discovery" procedure.
  void SetGeneralDiscoveryFlags();

  // Returns true, if the given LE scan result satisfies this filter. Otherwise
  // returns false. |advertising_data| should include scan response data, if
  // any.
  bool MatchLowEnergyResult(const ByteBuffer& advertising_data, bool connectable,
                            int8_t rssi) const;

  // Clears all the fields of this filter.
  void Reset();

 private:
  std::vector<UUID> service_uuids_;
  std::string name_substring_;
  std::optional<uint8_t> flags_;
  bool all_flags_required_;
  std::optional<bool> connectable_;
  std::optional<uint16_t> manufacturer_code_;
  std::optional<int8_t> pathloss_;
  std::optional<int8_t> rssi_;
};

}  // namespace gap
}  // namespace bt

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_GAP_DISCOVERY_FILTER_H_
