/**
 * @file CommunicationManager.hpp
 *
 * @brief Header file that declares the methods to manage the Cosmic packet protocol.
 */

#pragma once

#include <cstdint>
#include <functional>
#include <vector>

#include "CosmicDriver.hpp"
#include "UsbTransferProtocol.hpp"

class CommunicationManager {
public:
  /**
   * Type alias for the response callback function
   */
  using GenericResponseCallback = std::function<void(const std::vector<uint8_t>&)>;

  /**
   * Constructor: initializes the CommunicationManager and its components
   */
  CommunicationManager();

  /**
   * Destructor: cleans up the CommunicationManager and its components
   */
  ~CommunicationManager();

  /**
   * Connects to the device using the provided path or serial number.
   * @param devicePath The path to the device. If empty, connects using serialNumber or
   * first found device.
   * @param serialNumber The serial number of the device to connect to. If empty, connects
   * using devicePath or the first available device.
   * @return true if the connection was successful, false otherwise.
   */
  bool connect(const std::string& devicePath = "", const std::string& serialNumber = "");

  /**
   * Disconnects from the device.
   */
  void disconnect();

  /**
   * Sends a request to the device.
   * @param request The request data to be sent to the device.
   */
  void sendRequest(const std::vector<uint8_t>& request);

  /**
   * Assigns a callback function to be invoked when a full response is received.
   * @param callback The callback function to be invoked with the response data.
   */
  void assignCallback(GenericResponseCallback callback);

#ifdef __wasm__
  /**
   * Connects in WASM mode with a known endpoint size.
   * Bypasses enumeration-based endpoint detection.
   * @param endpointSize The endpoint size (64 for Supernova, 1024 for Pulsar).
   * @return true if the connection was successful, false otherwise.
   */
  bool connectWasm(uint16_t endpointSize);

  /**
   * Returns a callable that invokes the driver's pollOnce() method.
   * Used by CosmicSDK to wire the poll function to BlockingApi.
   * @return A std::function wrapping CosmicDriver::pollOnce()
   */
  std::function<void()> getPollFunction();

  /**
   * Pushes a raw HID input report into the response pipeline (WASM only).
   * Bypasses hid_read — the JS host feeds reports directly.
   * @param report The raw HID input report bytes.
   */
  void processInputReport(const std::vector<uint8_t>& report);

  /**
   * Returns a pointer to the underlying CosmicDriver (WASM only).
   */
  CosmicDriver* getDriver();
#endif

private:
  /// USB In Transfer buffer. Data sent by the device is saved here.
  std::vector<uint8_t> inTransfer;

  /// USB Out Transfers packet to be sent to the device.
  std::vector<std::vector<uint8_t>> outTransferPackets;

  /// USB transfer protocol instance
  std::unique_ptr<UsbTransferProtocol> transferProtocol;

  /// Cosmic driver instance
  std::unique_ptr<CosmicDriver> driver;

  /// Callback function to be invoked when a full response is received
  GenericResponseCallback onResponseCallback;

  /**
   * Callback function to be invoked when an input packet is received from the driver.
   * @param responseChunk The chunk of response data received from the driver.
   */
  void onDriverResponseCallback(const std::vector<uint8_t>& responseChunk);
};
