#ifndef LINUX_CSP_CSPCOMIF_H_
#define LINUX_CSP_CSPCOMIF_H_

#include <csp/csp.h>
#include <fsfw/devicehandlers/DeviceCommunicationIF.h>
#include <fsfw/objectmanager/SystemObject.h>
#include <fsfw/returnvalues/HasReturnvaluesIF.h>

#include <unordered_map>
#include <vector>

/**
 * @brief	This class serves as the communication interface to devices
 * 			supporting the CSP protocol. As physical layer can0 is used
 * 			in this implementation.
 * @author	J. Meier
 */
class CspComIF : public DeviceCommunicationIF, public SystemObject {
 public:
  CspComIF(object_id_t objectId);
  virtual ~CspComIF();

  ReturnValue_t initializeInterface(CookieIF *cookie) override;
  ReturnValue_t sendMessage(CookieIF *cookie, const uint8_t *sendData, size_t sendLen) override;
  ReturnValue_t getSendSuccess(CookieIF *cookie) override;
  ReturnValue_t requestReceiveMessage(CookieIF *cookie, size_t requestLen) override;
  ReturnValue_t readReceivedMessage(CookieIF *cookie, uint8_t **readData, size_t *readLen) override;

 private:
  /**
   * @brief	This function initiates the CSP transfer.
   *
   * @param cspAddress	The CSP address of the target device.
   * @param cspPort		The port of the target device.
   * @param timeout		The timeout to wait for csp_send and csp_read
   * 						functions. Specifies how long the functions wait
   * 						for a successful operation.
   * @param cmdBuffer		The data to send.
   * @param cmdLen   		The number of bytes to send.
   * @param querySize		The size of the requested message.
   */
  ReturnValue_t cspTransfer(uint8_t cspAddress, uint8_t cspPort, const uint8_t *cmdBuffer,
                            int cmdLen, uint16_t querySize);

  enum Ports { CSP_PING = 1, CSP_REBOOT = 4, P60_PORT_RPARAM = 7, P60_PORT_GNDWDT_RESET = 9 };

  typedef uint8_t node_t;
  using vectorBuffer = std::vector<uint8_t>;
  using VectorBufferMap = std::unordered_map<node_t, vectorBuffer>;
  using vectorBufferIter = VectorBufferMap::iterator;

  /* In this map assigns reply buffers to a CSP device */
  VectorBufferMap cspDeviceMap;

  uint16_t replySize = 0;

  /* This is the CSP address of the OBC. */
  node_t cspOwnAddress = 1;

  /* Interface struct for csp protocol stack */
  csp_iface_t csp_if;

  char canInterface[5] = "can0";
  int bitrate = 1000;

  /**
   * @brief	Function to extract the csp port and the query size from the
   * 			command buffer.
   */
  ReturnValue_t getPortAndQuerySize(const uint8_t **sendData, size_t *sendLen, uint8_t *cspPort,
                                    uint16_t *querySize);

  /**
   * @brief	This function initiates the ping request.
   */
  void initiatePingRequest(uint8_t cspAddress, uint16_t querySize);
};

#endif /* LINUX_CSP_CSPCOMIF_H_ */