/**
 * @file UsbTransferProtocol.hpp
 *
 * @brief Header file that declares the Messages Constructor class
 */

#pragma once

#include <stddef.h>
#include <stdint.h>

#include <iostream>
#include <vector>

class UsbTransferProtocol {
private:
  /// Endpoint size for the USB transfer protocol
  size_t endpointSize;

  /// Size of the payload of the USB packets depending on the size of the USB Transfer Packet Header
  /// and the size of the USB endpoint size.
  size_t packetPayloadLength;

public:
  /**
   * @brief Struct that represents the header of the USB packets.
   *
   */
  struct UsbTransferPacketHeader {
    uint16_t sot : 1;             // 1 bit for start of transfer
    uint16_t eot : 1;             // 1 bit for end of transfer
    uint16_t payloadLength : 10;  // 10 bits for payload length
    uint16_t reserved : 4;        // 4 bits for reserved space
  };

  /**
   * Constructor: initializes the USB transfer protocol with the specified type
   * @param endpointSize The endpoint size of the connected device.
   */
  UsbTransferProtocol(size_t endpointSize);

  /**
   * Destructor: cleans up the USB transfer protocol
   */
  ~UsbTransferProtocol();

  /**
   * Gets the endpoint size of the used in the USB transfers.
   * @return The endpoint size.
   */
  size_t getEndpointSize() const;

  /**
   * Gets the USB packets payload size.
   * @return The packets payload size.
   */
  size_t getPacketPayloadLength() const;

  /**
   * Creates USB OUT transfer packets to pack and send the data provided in the second argument.
   *
   * @param packets A vector in which the packets created will be store.
   * @param data The data to be sent in the USB transfer packets
   */
  void createUsbOutTransferPackets(std::vector<std::vector<uint8_t>>& packets, const std::vector<uint8_t>& data);

  /**
   * Receives USB IN transfer packets and assembles them into a single message.
   *
   * @param inputBuffer a plain vector of bytes in which the whole IN transfer is store.
   * @param data A new USB IN packet sent by teh USB device.
   * @return A boolean indicating if the IN transfer is complete or ti must wait for a new IN packet.
   */
  bool receiveUsbInTransferPackets(std::vector<uint8_t>& inputBuffer, const std::vector<uint8_t>& data);
};