// Copyright 2020 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_l2cap.h"

#include <endian.h>
#include <zircon/assert.h>

namespace bt::testing {

FakeL2cap::FakeL2cap(SendFrameCallback send_frame_callback,
                     UnexpectedPduCallback unexpected_pdu_callback,
                     l2cap::ChannelId largest_channel_id)
    : send_frame_callback_(std::move(send_frame_callback)),
      unexpected_pdu_callback_(std::move(unexpected_pdu_callback)),
      largest_channel_id_(largest_channel_id) {}

void FakeL2cap::RegisterHandler(l2cap::ChannelId cid, ChannelReceiveCallback callback) {
  ZX_ASSERT(cid < l2cap::kFirstDynamicChannelId);
  if (callbacks_.find(cid) != callbacks_.end()) {
    bt_log(WARN, "fake-hci", "Overwriting previous handler for Channel ID %hu", cid);
  }
  callbacks_.insert_or_assign(cid, std::move(callback));
}

void FakeL2cap::RegisterService(l2cap::PSM psm, FakeDynamicChannelCallback callback) {
  if (callbacks_.find(psm) != callbacks_.end()) {
    bt_log(WARN, "fake-hci", "Overwriting previous handler for PSM %.4hu", psm);
  }
  registered_services_.insert_or_assign(psm, std::move(callback));
}

bool FakeL2cap::RegisterDynamicChannel(hci::ConnectionHandle conn, l2cap::PSM psm,
                                       l2cap::ChannelId local_cid, l2cap::ChannelId remote_cid) {
  ZX_ASSERT(local_cid >= l2cap::kFirstDynamicChannelId);
  auto channel_map = dynamic_channels_.find(conn);
  if (channel_map != dynamic_channels_.end()) {
    if (channel_map->second.find(local_cid) == channel_map->second.end()) {
      bt_log(ERROR, "fake-hci", "Dynamic channel already exists at handle %hu and Channel ID %hu",
             conn, local_cid);
      return false;
    }
  }
  if (!ServiceRegisteredForPsm(psm)) {
    bt_log(ERROR, "fake-hci", "No service registered for psm %hu", psm);
    return false;
  }
  if (dynamic_channels_.find(conn) == dynamic_channels_.end()) {
    std::unordered_map<l2cap::ChannelId, std::unique_ptr<FakeDynamicChannel>> new_conn_map;
    dynamic_channels_.emplace(conn, std::move(new_conn_map));
  }
  dynamic_channels_.find(conn)->second.insert_or_assign(
      local_cid, std::make_unique<FakeDynamicChannel>(conn, psm, local_cid, remote_cid));
  return true;
}

bool FakeL2cap::RegisterDynamicChannelWithPsm(hci::ConnectionHandle conn,
                                              l2cap::ChannelId local_cid) {
  auto channel = FindDynamicChannelByLocalId(conn, local_cid);
  if (channel) {
    ZX_ASSERT(channel->opened());
    auto psm_iter = registered_services_.find(channel->psm());
    if (psm_iter == registered_services_.end()) {
      bt_log(ERROR, "fake-hci", "No service registered for psm %hu", channel->psm());
      return false;
    }
    psm_iter->second(channel);
    // If the callback does not assign a send_packet_callback, default to
    // FakeL2cap's version.
    if (!channel->send_packet_callback()) {
      auto send_cb = [this, channel](auto& packet) -> void {
        auto& l2cap_callback = this->send_frame_callback();
        l2cap_callback(channel->handle(), channel->local_cid(), packet);
      };
      channel->set_send_packet_callback(send_cb);
    }
    return true;
  }
  return false;
}

bool FakeL2cap::ServiceRegisteredForPsm(l2cap::PSM psm) {
  auto iter = registered_services_.find(psm);
  if (iter == registered_services_.end()) {
    return false;
  }
  return true;
}

l2cap::ChannelId FakeL2cap::FindAvailableDynamicChannelId(hci::ConnectionHandle conn) {
  auto channel_map = dynamic_channels_.find(conn);
  // If there are no dynamic channel connections on the ConnectHandle, assign
  // it the first ID
  if (channel_map == dynamic_channels_.end()) {
    return l2cap::kFirstDynamicChannelId;
  }
  for (l2cap::ChannelId id = l2cap::kFirstDynamicChannelId; id < largest_channel_id_ + 1; id++) {
    if (channel_map->second.count(id) == 0) {
      return id;
    }
  }
  return l2cap::kInvalidChannelId;
}

fxl::WeakPtr<FakeDynamicChannel> FakeL2cap::FindDynamicChannelByLocalId(
    hci::ConnectionHandle conn, l2cap::ChannelId local_cid) {
  auto channel_map = dynamic_channels_.find(conn);
  if (channel_map == dynamic_channels_.end()) {
    return nullptr;
  }
  auto channel = channel_map->second.find(local_cid);
  if (channel == channel_map->second.end()) {
    return nullptr;
  }
  return channel->second->AsWeakPtr();
}

fxl::WeakPtr<FakeDynamicChannel> FakeL2cap::FindDynamicChannelByRemoteId(
    hci::ConnectionHandle conn, l2cap::ChannelId remote_cid) {
  auto channel_map = dynamic_channels_.find(conn);
  if (channel_map == dynamic_channels_.end()) {
    return nullptr;
  }
  for (auto& [id, channel_ptr] : channel_map->second) {
    if (channel_ptr->remote_cid() == remote_cid) {
      return channel_ptr->AsWeakPtr();
    }
  }
  return nullptr;
}

void FakeL2cap::DeleteDynamicChannelByLocalId(hci::ConnectionHandle conn,
                                              l2cap::ChannelId local_cid) {
  auto channel_map = dynamic_channels_.find(conn);
  if (channel_map == dynamic_channels_.end()) {
    bt_log(ERROR, "hci-fake", "Attempt to delete unregistered channel.");
    return;
  }
  auto channel = channel_map->second.find(local_cid);
  if (channel == channel_map->second.end()) {
    bt_log(ERROR, "hci-fake", "Attempt to delete unregistered channel.");
    return;
  }
  channel->second = nullptr;
  dynamic_channels_[conn].erase(local_cid);
}

void FakeL2cap::HandlePdu(hci::ConnectionHandle conn, const ByteBuffer& pdu) {
  if (pdu.size() < sizeof(l2cap::BasicHeader)) {
    bt_log(WARN, "fake-hci", "malformed L2CAP packet!");
    return;
  }

  // Extract channel ID and strip the L2CAP header from the pdu.
  const auto& header = pdu.As<l2cap::BasicHeader>();
  l2cap::ChannelId cid = le16toh(header.channel_id);
  auto header_len = sizeof(header);
  auto payload_len = le16toh(header.length);
  auto sdu = DynamicByteBuffer(payload_len);
  pdu.Copy(&sdu, header_len, payload_len);

  // Execute corresponding handler function based on the channel type.
  if (cid < l2cap::kFirstDynamicChannelId) {
    auto handler = callbacks_.find(cid);
    if (handler == callbacks_.end()) {
      return unexpected_pdu_callback_(conn, pdu);
    } else {
      return handler->second(conn, sdu);
    }
  } else {
    auto channel = FindDynamicChannelByLocalId(conn, cid);
    if (channel) {
      auto& callback = channel->packet_handler_callback();
      return callback(sdu);
    }
  }
  return unexpected_pdu_callback_(conn, pdu);
}

}  // namespace bt::testing
