// 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_TESTING_CONTROLLER_TEST_DOUBLE_BASE_H_
#define SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_TESTING_CONTROLLER_TEST_DOUBLE_BASE_H_

#include <lib/async/cpp/wait.h>
#include <lib/zx/channel.h>
#include <zircon/device/bt-hci.h>

#include <fbl/macros.h>

#include "src/connectivity/bluetooth/core/bt-host/common/byte_buffer.h"
#include "src/connectivity/bluetooth/core/bt-host/common/packet_view.h"
#include "src/connectivity/bluetooth/core/bt-host/hci-spec/protocol.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/acl_data_packet.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/control_packets.h"
#include "src/connectivity/bluetooth/core/bt-host/transport/sco_data_packet.h"

namespace bt::testing {

// Abstract base for implementing a fake HCI controller endpoint. This can
// directly send ACL data and event packets on request and forward outgoing ACL
// data packets to subclass implementations.
class ControllerTestDoubleBase {
 public:
  ControllerTestDoubleBase();
  virtual ~ControllerTestDoubleBase();

  // Sets a callback that will be called when an error is signaled with SignalError().
  void set_error_callback(fit::callback<void(zx_status_t)> callback) {
    error_cb_ = std::move(callback);
  }

  // Closes all open channels and signals |status| to the error callback.
  void Stop(zx_status_t status = ZX_ERR_PEER_CLOSED);

  // Sends the given packet over this FakeController's command channel endpoint.
  // Returns the result of the write operation on the command channel.
  zx_status_t SendCommandChannelPacket(const ByteBuffer& packet);

  // Sends the given packet over this FakeController's ACL data channel
  // endpoint.
  // Returns the result of the write operation on the channel.
  zx_status_t SendACLDataChannelPacket(const ByteBuffer& packet);

  // Sends the given packet over this ControllerTestDouble's SCO data channel
  // endpoint.
  // Returns the result of the write operation on the channel.
  zx_status_t SendScoDataChannelPacket(const ByteBuffer& packet);

  // Sends the given packet over this FakeController's Snoop channel endpoint.
  // Returns the result of the write operation on the channel.
  void SendSnoopChannelPacket(const ByteBuffer& packet, bt_hci_snoop_type_t packet_type,
                              bool is_received);

  // Immediately closes the Snoop channel endpoint.
  void CloseSnoopChannel();

  // Starts listening for event packets with the given callback.
  void StartCmdChannel(fit::function<void(std::unique_ptr<hci::EventPacket>)> packet_cb);

  // Starts listening for ACL packets with the given callback.
  void StartAclChannel(fit::function<void(std::unique_ptr<hci::ACLDataPacket>)> packet_cb);

  // Starts listening for SCO packets with the given callback.
  void StartScoChannel(fit::function<void(std::unique_ptr<hci::ScoDataPacket>)> packet_cb);

  // Starts listening for snoop packets on the given channel.
  // Returns false if already listening on a snoop channel
  bool StartSnoopChannel(zx::channel chan);

  // Called by test fixtures to send packets:
  void HandleCommandPacket(std::unique_ptr<hci::CommandPacket> packet);
  void HandleACLPacket(std::unique_ptr<hci::ACLDataPacket> packet);
  void HandleScoPacket(std::unique_ptr<hci::ScoDataPacket> packet);

 protected:
  void SignalError(zx_status_t status) {
    if (error_cb_) {
      error_cb_(status);
    }
  }

  const zx::channel& snoop_channel() const { return snoop_channel_; }

  // Called when there is an outgoing command packet.
  virtual void OnCommandPacketReceived(
      const PacketView<hci_spec::CommandHeader>& command_packet) = 0;

  // Called when there is an outgoing ACL data packet.
  virtual void OnACLDataPacketReceived(const ByteBuffer& acl_data_packet) = 0;

  // Called when there is an outgoing SCO data packet.
  virtual void OnScoDataPacketReceived(const ByteBuffer& sco_data_packet) = 0;

 private:
  zx::channel snoop_channel_;

  // Send inbound packets to the host stack:
  fit::function<void(std::unique_ptr<hci::EventPacket>)> send_event_;
  fit::function<void(std::unique_ptr<hci::ACLDataPacket>)> send_acl_packet_;
  fit::function<void(std::unique_ptr<hci::ScoDataPacket>)> send_sco_packet_;

  fit::callback<void(zx_status_t)> error_cb_;

  DISALLOW_COPY_AND_ASSIGN_ALLOW_MOVE(ControllerTestDoubleBase);
};

}  // namespace bt::testing

#endif  // SRC_CONNECTIVITY_BLUETOOTH_CORE_BT_HOST_TESTING_CONTROLLER_TEST_DOUBLE_BASE_H_
