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

#include "fake_domain.h"

#include <lib/async/cpp/task.h>
#include <lib/async/default.h>
#include <zircon/assert.h>

#include "src/connectivity/bluetooth/core/bt-host/l2cap/fake_channel.h"
#include "src/connectivity/bluetooth/core/bt-host/l2cap/l2cap.h"

namespace bt {

using l2cap::testing::FakeChannel;

namespace data {
namespace testing {
namespace {

// Use plausible ERTM parameters that do not necessarily match values in production. See Core Spec
// v5.0 Vol 3, Part A, Sec 5.4 for meanings.
constexpr uint8_t kErtmNFramesInTxWindow = 32;
constexpr uint8_t kErtmMaxTransmissions = 8;
constexpr uint16_t kMaxTxPduPayloadSize = 1024;

}  // namespace

bool FakeDomain::IsLinkConnected(hci::ConnectionHandle handle) const {
  auto link_iter = links_.find(handle);
  if (link_iter == links_.end()) {
    return false;
  }
  return link_iter->second.connected;
}

void FakeDomain::TriggerLEConnectionParameterUpdate(
    hci::ConnectionHandle handle, const hci::LEPreferredConnectionParameters& params) {
  LinkData& link_data = ConnectedLinkData(handle);
  link_data.le_conn_param_cb(params);
}

void FakeDomain::ExpectOutboundL2capChannel(hci::ConnectionHandle handle, l2cap::PSM psm,
                                            l2cap::ChannelId id, l2cap::ChannelId remote_id,
                                            l2cap::ChannelParameters params) {
  LinkData& link_data = GetLinkData(handle);
  ChannelData chan_data;
  chan_data.local_id = id;
  chan_data.remote_id = remote_id;
  chan_data.params = params;
  link_data.expected_outbound_conns[psm].push(chan_data);
}

bool FakeDomain::TriggerInboundL2capChannel(hci::ConnectionHandle handle, l2cap::PSM psm,
                                            l2cap::ChannelId id, l2cap::ChannelId remote_id,
                                            uint16_t max_tx_sdu_size) {
  LinkData& link_data = ConnectedLinkData(handle);
  auto cb_iter = registered_services_.find(psm);

  // No service registered for the PSM.
  if (cb_iter == registered_services_.end()) {
    return false;
  }

  l2cap::ChannelCallback& cb = cb_iter->second.channel_cb;
  auto chan_params = cb_iter->second.channel_params;
  auto mode = chan_params.mode.value_or(l2cap::ChannelMode::kBasic);
  auto max_rx_sdu_size = chan_params.max_rx_sdu_size.value_or(l2cap::kDefaultMTU);
  auto channel_info = l2cap::ChannelInfo::MakeBasicMode(max_rx_sdu_size, max_tx_sdu_size);
  if (mode == l2cap::ChannelMode::kEnhancedRetransmission) {
    channel_info = l2cap::ChannelInfo::MakeEnhancedRetransmissionMode(
        max_rx_sdu_size, max_tx_sdu_size, /*n_frames_in_tx_window=*/kErtmNFramesInTxWindow,
        /*max_transmissions=*/kErtmMaxTransmissions,
        /*max_tx_pdu_payload_size=*/kMaxTxPduPayloadSize);
  }

  auto chan = OpenFakeChannel(&link_data, id, remote_id, channel_info);
  cb(std::move(chan));

  return true;
}

void FakeDomain::TriggerLinkError(hci::ConnectionHandle handle) {
  LinkData& link_data = ConnectedLinkData(handle);
  link_data.link_error_cb();
}

void FakeDomain::AddACLConnection(hci::ConnectionHandle handle, hci::Connection::Role role,
                                  l2cap::LinkErrorCallback link_error_cb,
                                  l2cap::SecurityUpgradeCallback security_cb) {
  RegisterInternal(handle, role, hci::Connection::LinkType::kACL, std::move(link_error_cb));
}

void FakeDomain::AddLEConnection(hci::ConnectionHandle handle, hci::Connection::Role role,
                                 l2cap::LinkErrorCallback link_error_cb,
                                 l2cap::LEConnectionParameterUpdateCallback conn_param_cb,
                                 l2cap::LEFixedChannelsCallback channel_cb,
                                 l2cap::SecurityUpgradeCallback security_cb) {
  LinkData* data =
      RegisterInternal(handle, role, hci::Connection::LinkType::kLE, std::move(link_error_cb));
  data->le_conn_param_cb = std::move(conn_param_cb);

  // Open the ATT and SMP fixed channels.
  auto att = OpenFakeFixedChannel(data, l2cap::kATTChannelId);
  auto smp = OpenFakeFixedChannel(data, l2cap::kLESMPChannelId);
  channel_cb(std::move(att), std::move(smp));
}

void FakeDomain::RemoveConnection(hci::ConnectionHandle handle) { links_.erase(handle); }

void FakeDomain::AssignLinkSecurityProperties(hci::ConnectionHandle handle,
                                              sm::SecurityProperties security) {
  // TODO(armansito): implement
}

void FakeDomain::RequestConnectionParameterUpdate(
    hci::ConnectionHandle handle, hci::LEPreferredConnectionParameters params,
    l2cap::ConnectionParameterUpdateRequestCallback request_cb, async_dispatcher_t* dispatcher) {
  bool response = connection_parameter_update_request_responder_
                      ? connection_parameter_update_request_responder_(handle, params)
                      : true;
  async::PostTask(dispatcher, std::bind(std::move(request_cb), response));
}

void FakeDomain::OpenL2capChannel(hci::ConnectionHandle handle, l2cap::PSM psm,
                                  l2cap::ChannelParameters params, l2cap::ChannelCallback cb,
                                  async_dispatcher_t* dispatcher) {
  LinkData& link_data = ConnectedLinkData(handle);
  auto psm_it = link_data.expected_outbound_conns.find(psm);

  ZX_DEBUG_ASSERT_MSG(psm_it != link_data.expected_outbound_conns.end() && !psm_it->second.empty(),
                      "Unexpected outgoing L2CAP connection (PSM %#.4x)", psm);

  auto chan_data = psm_it->second.front();
  psm_it->second.pop();

  auto mode = params.mode.value_or(l2cap::ChannelMode::kBasic);
  auto max_rx_sdu_size = params.max_rx_sdu_size.value_or(l2cap::kMaxMTU);

  ZX_ASSERT_MSG(chan_data.params == params,
                "Didn't receive expected L2CAP channel parameters (expected: %s, found: %s)",
                bt_str(chan_data.params), bt_str(params));

  auto channel_info = l2cap::ChannelInfo::MakeBasicMode(max_rx_sdu_size, l2cap::kDefaultMTU);
  if (mode == l2cap::ChannelMode::kEnhancedRetransmission) {
    channel_info = l2cap::ChannelInfo::MakeEnhancedRetransmissionMode(
        max_rx_sdu_size, l2cap::kDefaultMTU, /*n_frames_in_tx_window=*/kErtmNFramesInTxWindow,
        /*max_transmissions=*/kErtmMaxTransmissions,
        /*max_tx_pdu_payload_size=*/kMaxTxPduPayloadSize);
  }

  auto chan = OpenFakeChannel(&link_data, chan_data.local_id, chan_data.remote_id, channel_info);

  async::PostTask(dispatcher,
                  [cb = std::move(cb), chan = std::move(chan)]() { cb(std::move(chan)); });
}

void FakeDomain::OpenL2capChannel(hci::ConnectionHandle handle, l2cap::PSM psm,
                                  l2cap::ChannelParameters params, SocketCallback socket_callback,
                                  async_dispatcher_t* cb_dispatcher) {
  ZX_DEBUG_ASSERT(cb_dispatcher);
  OpenL2capChannel(
      handle, psm, params,
      [this, cb = std::move(socket_callback), handle, cb_dispatcher](auto channel) mutable {
        zx::socket s = socket_factory_.MakeSocketForChannel(channel);
        auto chan_info = channel ? std::optional(channel->info()) : std::nullopt;
        l2cap::ChannelSocket chan_sock(std::move(s), chan_info);

        // Called every time the service is connected, cb must be shared.
        async::PostTask(cb_dispatcher,
                        [chan_sock = std::move(chan_sock), cb = cb.share(),
                         handle = handle]() mutable { cb(std::move(chan_sock), handle); });
      },
      async_get_default_dispatcher());
}

void FakeDomain::RegisterService(l2cap::PSM psm, l2cap::ChannelParameters params,
                                 l2cap::ChannelCallback channel_callback,
                                 async_dispatcher_t* dispatcher) {
  ZX_DEBUG_ASSERT(registered_services_.count(psm) == 0);

  // capture |dispatcher| here so it doesn't need to be stored with ServiceInfo
  auto service_cb = [dispatcher, chan_cb = std::move(channel_callback)](auto chan) mutable {
    async::PostTask(dispatcher,
                    [cb = chan_cb.share(), chan = std::move(chan)]() { cb(std::move(chan)); });
  };
  registered_services_.emplace(psm, ServiceInfo(params, std::move(service_cb)));
}

void FakeDomain::RegisterService(l2cap::PSM psm, l2cap::ChannelParameters params,
                                 SocketCallback socket_callback,
                                 async_dispatcher_t* cb_dispatcher) {
  RegisterService(
      psm, params,
      [this, cb = std::move(socket_callback), cb_dispatcher](auto channel) mutable {
        zx::socket s = socket_factory_.MakeSocketForChannel(channel);
        auto chan_info = channel ? std::optional(channel->info()) : std::nullopt;
        l2cap::ChannelSocket chan_sock(std::move(s), chan_info);

        // Called every time the service is connected, cb must be shared.
        async::PostTask(cb_dispatcher, [chan_sock = std::move(chan_sock), cb = cb.share(),
                                        handle = channel->link_handle()]() mutable {
          cb(std::move(chan_sock), handle);
        });
      },
      async_get_default_dispatcher());
}

void FakeDomain::UnregisterService(l2cap::PSM psm) { registered_services_.erase(psm); }

FakeDomain::~FakeDomain() {
  for (auto& link_it : links_) {
    for (auto& psm_it : link_it.second.expected_outbound_conns) {
      ZX_DEBUG_ASSERT_MSG(psm_it.second.empty(), "didn't receive expected connection on PSM %#.4x",
                          psm_it.first);
    }
  }
}

FakeDomain::LinkData* FakeDomain::RegisterInternal(hci::ConnectionHandle handle,
                                                   hci::Connection::Role role,
                                                   hci::Connection::LinkType link_type,
                                                   l2cap::LinkErrorCallback link_error_cb) {
  auto& data = GetLinkData(handle);
  ZX_DEBUG_ASSERT_MSG(!data.connected, "connection handle re-used (handle: %#.4x)", handle);

  data.connected = true;
  data.role = role;
  data.type = link_type;
  data.link_error_cb = std::move(link_error_cb);

  return &data;
}

fbl::RefPtr<FakeChannel> FakeDomain::OpenFakeChannel(LinkData* link, l2cap::ChannelId id,
                                                     l2cap::ChannelId remote_id,
                                                     l2cap::ChannelInfo info) {
  fbl::RefPtr<FakeChannel> chan;
  if (!simulate_open_channel_failure_) {
    chan = fbl::AdoptRef(new FakeChannel(id, remote_id, link->handle, link->type, info));
    chan->SetLinkErrorCallback(link->link_error_cb.share());
  }

  if (chan_cb_) {
    chan_cb_(chan);
  }

  return chan;
}

fbl::RefPtr<FakeChannel> FakeDomain::OpenFakeFixedChannel(LinkData* link, l2cap::ChannelId id) {
  return OpenFakeChannel(link, id, id);
}

FakeDomain::LinkData& FakeDomain::GetLinkData(hci::ConnectionHandle handle) {
  auto [it, inserted] = links_.try_emplace(handle);
  auto& data = it->second;
  if (inserted) {
    data.connected = false;
    data.handle = handle;
  }
  return data;
}

FakeDomain::LinkData& FakeDomain::ConnectedLinkData(hci::ConnectionHandle handle) {
  auto link_iter = links_.find(handle);
  ZX_DEBUG_ASSERT_MSG(link_iter != links_.end(), "fake link not found (handle: %#.4x)", handle);
  ZX_DEBUG_ASSERT_MSG(link_iter->second.connected, "fake link not connected yet (handle: %#.4x)",
                      handle);
  return link_iter->second;
}

}  // namespace testing
}  // namespace data
}  // namespace bt
