// Copyright 2019 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 "src/connectivity/bluetooth/core/bt-host/l2cap/enhanced_retransmission_mode_rx_engine.h"

#include <type_traits>

namespace bt {
namespace l2cap {
namespace internal {

namespace {

template <typename T>
std::optional<T> TryCopyFromPdu(const PDU& pdu) {
  if (pdu.length() < sizeof(T))
    return std::nullopt;

  StaticByteBuffer<sizeof(T)> buf;
  pdu.Copy(&buf, 0, sizeof(T));
  return buf.template As<T>();
}

std::variant<std::monostate, const SimpleInformationFrameHeader, const SimpleStartOfSduFrameHeader,
             const SimpleSupervisoryFrame>
GetFrameHeaderFromPdu(const PDU& pdu) {
  const auto control_field_opt = TryCopyFromPdu<EnhancedControlField>(pdu);
  if (!control_field_opt) {
    // TODO(BT-713): Add metric counting runt frames.
    return std::monostate();
  }

  const auto& control_field = control_field_opt.value();
  if (control_field.designates_supervisory_frame()) {
    const auto frame_opt = TryCopyFromPdu<SimpleSupervisoryFrame>(pdu);
    if (!frame_opt) {
      // TODO(BT-713): Add metric counting runt S-frames.
      return std::monostate();
    }
    return frame_opt.value();
  }

  if (control_field.designates_start_of_segmented_sdu()) {
    const auto frame_opt = TryCopyFromPdu<SimpleStartOfSduFrameHeader>(pdu);
    if (!frame_opt) {
      // TODO(BT-713): Add metric counting runt Start-of-SDU frames.
      return std::monostate();
    }
    return frame_opt.value();
  }

  const auto frame_opt = TryCopyFromPdu<SimpleInformationFrameHeader>(pdu);
  if (!frame_opt) {
    // TODO(BT-713): Add metric counting runt I-frames.
    return std::monostate();
  }
  return frame_opt.value();
}

template <typename T>
constexpr bool kContainsEnhancedControlField = std::is_base_of_v<EnhancedControlField, T>;

bool IsMpsValid(const PDU& pdu) {
  // TODO(quiche): Check PDU's length against the MPS.
  return true;
}

}  // namespace

using Engine = EnhancedRetransmissionModeRxEngine;

Engine::EnhancedRetransmissionModeRxEngine(SendFrameCallback send_frame_callback)
    : next_seqnum_(0), send_frame_callback_(std::move(send_frame_callback)) {}

ByteBufferPtr Engine::ProcessPdu(PDU pdu) {
  // A note on validation (see Vol 3, Part A, 3.3.7):
  //
  // We skip step 1 (validation of the Channel ID), as a frame with an
  // unrecognized Channel ID will not be delivered to us. (Various
  // L2CAP_ChannelManagerTest test cases verify that LogicalLink directs frames
  // to their proper channels.)
  //
  // We skip step 2 (validation of FCS), as we don't support FCS.
  //
  // Step 3 (size checking) is implemented in IsMpsValid(), and
  // GetFrameHeaderFromPdu().
  //
  // TODO(quiche): Implement step 4/5 (Check SAR bits, close connection on
  // error).

  if (!IsMpsValid(pdu)) {
    // TODO(quiche): Close connection.
    // TODO(BT-713): Add metric counting oversized frames.
    return nullptr;
  }

  auto header = GetFrameHeaderFromPdu(pdu);
  auto frame_processor = [this, pdu = std::move(pdu)](auto header) mutable {
    if constexpr (kContainsEnhancedControlField<decltype(header)>) {
      if (receive_seq_num_callback_) {
        receive_seq_num_callback_(header.receive_seq_num(), header.is_poll_response());
      }
    }
    return ProcessFrame(header, std::move(pdu));
  };
  return std::visit(std::move(frame_processor), header);
}

ByteBufferPtr Engine::ProcessFrame(const SimpleInformationFrameHeader header, PDU pdu) {
  if (header.tx_seq() != next_seqnum_) {
    // TODO(quiche): Send REJ frame.
    // TODO(quiche): Add histogram for |header.tx_seq() - next_seqnum_|. This
    // will give us an upper bound on the potential benefit of sending SREJ
    // frames.
    return nullptr;
  }

  // TODO(quiche): check if the frame is within the permitted window.

  if (header.designates_part_of_segmented_sdu()) {
    // TODO(quiche): Implement validation and handling of segmented frames.
    return nullptr;
  }

  AdvanceSeqNum();

  if (ack_seq_num_callback_) {
    ack_seq_num_callback_(next_seqnum_);
  }

  SimpleReceiverReadyFrame ack_frame;
  ack_frame.set_receive_seq_num(next_seqnum_);
  send_frame_callback_(
      std::make_unique<DynamicByteBuffer>(BufferView(&ack_frame, sizeof(ack_frame))));

  const auto header_len = sizeof(header);
  const auto footer_len = sizeof(FrameCheckSequence);
  if (pdu.length() < header_len + footer_len) {
    return nullptr;
  }
  const auto payload_len = pdu.length() - header_len - footer_len;
  auto sdu = std::make_unique<DynamicByteBuffer>(payload_len);
  pdu.Copy(sdu.get(), header_len, payload_len);
  return sdu;
}

ByteBufferPtr Engine::ProcessFrame(const SimpleStartOfSduFrameHeader, PDU pdu) {
  // TODO(quiche): Implement validation and handling of Start-of-SDU frames.
  return nullptr;
}

ByteBufferPtr Engine::ProcessFrame(const SimpleSupervisoryFrame sframe, PDU pdu) {
  if (sframe.function() == SupervisoryFunction::ReceiverReady && sframe.is_poll_request()) {
    // TODO(quiche): Propagate ReqSeq to the transmit engine.
    // See Core Spec, v5, Vol 3, Part A, Section 8.6.5.9, Table 8.6, "Recv RR(P=1)".
    //
    // Note, however, that there may be additional work to do if we're in the
    // REJ_SENT state. See Core Spec, v5, Vol 3, Part A, Section 8.6.5.10, Table 8.7, "Recv
    // RR(P=1)".
    SimpleReceiverReadyFrame poll_response;
    poll_response.set_is_poll_response();
    poll_response.set_receive_seq_num(next_seqnum_);
    send_frame_callback_(
        std::make_unique<DynamicByteBuffer>(BufferView(&poll_response, sizeof(poll_response))));
    return nullptr;
  }

  // TODO(quiche): Implement handling of other S-frames.
  return nullptr;
}

ByteBufferPtr Engine::ProcessFrame(std::monostate, PDU pdu) {
  // TODO(quiche): Close connection.
  return nullptr;
}

void Engine::AdvanceSeqNum() {
  ++next_seqnum_;
  if (next_seqnum_ > EnhancedControlField::kMaxSeqNum) {
    next_seqnum_ = 0;
  }
}

}  // namespace internal
}  // namespace l2cap
}  // namespace bt
