#ifndef LINUX_CSP_CSPCOMIF_H_
#define LINUX_CSP_CSPCOMIF_H_

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

#include <vector>
#include <unordered_map>

/**
 * @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 cspClientAddress = 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_ */