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

#pragma once

#include <unordered_set>

#include "garnet/drivers/bluetooth/lib/common/byte_buffer.h"
#include "garnet/drivers/bluetooth/lib/common/device_address.h"
#include "garnet/drivers/bluetooth/lib/hci/connection.h"
#include "garnet/drivers/bluetooth/lib/hci/connection_parameters.h"
#include "garnet/drivers/bluetooth/lib/hci/hci.h"
#include "garnet/drivers/bluetooth/lib/testing/fake_gatt_server.h"
#include "lib/fxl/macros.h"

namespace btlib {
namespace testing {

class FakeController;

// FakeDevice is used to emulate a remote Bluetooth device.
class FakeDevice {
 public:
  // NOTE: Setting |connectable| to true will result in a "Connectable and
  // Scannable Advertisement" (i.e. ADV_IND) even if |scannable| is set to
  // false. This is OK since we use |scannable| to drive the receipt of Scan
  // Response PDUs: we use this to test the condition in which the advertisement
  // is scannable but the host never receives a scan response.
  explicit FakeDevice(const common::DeviceAddress& address,
                      bool connectable = true,
                      bool scannable = true);

  void SetAdvertisingData(const common::ByteBuffer& data);

  bool has_advertising_reports() {
    return (adv_data_.size() > 0) || (scan_rsp_.size() > 0);
  };

  bool has_inquiry_response() {
    // All BR/EDR devices have inquiry responses.
    return address().type() == common::DeviceAddress::Type::kBREDR;
  };

  // |should_batch_reports| indicates to the FakeController that the SCAN_IND
  // report should be included in the same HCI LE Advertising Report Event
  // payload that includes the original advertising data (see comments for
  // should_batch_reports()).
  void SetScanResponse(bool should_batch_reports,
                       const common::ByteBuffer& data);

  // Generates and returns a LE Advertising Report Event payload. If
  // |include_scan_rsp| is true, then the returned PDU will contain two reports
  // including the SCAN_IND report.
  common::DynamicByteBuffer CreateAdvertisingReportEvent(
      bool include_scan_rsp) const;

  // Generates a LE Advertising Report Event payload containing the scan
  // response.
  common::DynamicByteBuffer CreateScanResponseReportEvent() const;

  // Generates a Inquiry Response Event payload containing a inquiry result
  // response.
  common::DynamicByteBuffer CreateInquiryResponseEvent(
      hci::InquiryMode mode) const;

  const common::DeviceAddress& address() const { return address_; }

  // Indicates whether or not this device should include the scan response and
  // the advertising data in the same HCI LE Advertising Report Event. This is
  // used to test that the host stack can correctly consolidate advertising
  // reports when the payloads are spread across events and when they are
  // batched together in the same event.
  //
  // This isn't used by FakeDevice directly to generated batched reports. Rather
  // it is a hint to the corresponding FakeController which decides how the
  // reports should be generated.
  bool should_batch_reports() const { return should_batch_reports_; }

  // Returns true if this device is scannable. We use this to tell
  // FakeController whether or not it should send scan response PDUs.
  bool scannable() const { return scannable_; }

  bool connectable() const { return connectable_; }

  bool connected() const { return connected_; }
  void set_connected(bool connected) { connected_ = connected; }

  void set_class_of_device(common::DeviceClass class_of_device) {
    class_of_device_ = class_of_device;
  }

  const hci::LEConnectionParameters& le_params() const { return le_params_; }
  void set_le_params(const hci::LEConnectionParameters& value) {
    le_params_ = value;
  }

  // The response status that will be returned when this device receives a LE
  // Create Connection command.
  hci::StatusCode connect_response() const { return connect_response_; }
  void set_connect_response(hci::StatusCode response) {
    connect_response_ = response;
  }

  // The status that will be returned in the Command Status event in response to
  // a LE Create Connection command. If this is set to anything other than
  // hci::StatusCode::kSuccess, then connect_response() will have no effect.
  hci::StatusCode connect_status() const { return connect_status_; }
  void set_connect_status(hci::StatusCode status) { connect_status_ = status; }

  bool force_pending_connect() const { return force_pending_connect_; }
  void set_force_pending_connect(bool value) { force_pending_connect_ = value; }

  void AddLink(hci::ConnectionHandle handle);
  void RemoveLink(hci::ConnectionHandle handle);
  bool HasLink(hci::ConnectionHandle handle) const;

  using HandleSet = std::unordered_set<hci::ConnectionHandle>;
  const HandleSet& logical_links() const { return logical_links_; }

  // Marks this device as disconnected. Clears and returns all logical link
  // handles.
  HandleSet Disconnect();

  // Returns the FakeController that has been assigned to this device.
  FakeController* ctrl() const { return ctrl_; }

 private:
  friend class FakeController;

  // Called by a FakeController when a FakeDevice is registered with it.
  void set_ctrl(FakeController* ctrl) { ctrl_ = ctrl; }

  void WriteScanResponseReport(hci::LEAdvertisingReportData* report) const;

  void OnRxL2CAP(hci::ConnectionHandle conn, const common::ByteBuffer& pdu);

  // The FakeController that this FakeDevice has been assigned to.
  FakeController* ctrl_;  // weak

  common::DeviceAddress address_;
  bool connected_;
  bool connectable_;
  bool scannable_;

  hci::StatusCode connect_status_;
  hci::StatusCode connect_response_;
  bool force_pending_connect_;  // Causes connection requests to remain pending.

  hci::LEConnectionParameters le_params_;

  bool should_batch_reports_;
  common::DynamicByteBuffer adv_data_;
  common::DynamicByteBuffer scan_rsp_;

  // Open connection handles.
  HandleSet logical_links_;

  // Class of device
  common::DeviceClass class_of_device_;

  FakeGattServer gatt_server_;

  FXL_DISALLOW_COPY_AND_ASSIGN(FakeDevice);
};

}  // namespace testing
}  // namespace btlib
