#ifndef MISSION_DEVICES_GOMSPACEDEVICEHANDLER_H_
#define MISSION_DEVICES_GOMSPACEDEVICEHANDLER_H_

#include <fsfw/devicehandlers/DeviceHandlerBase.h>
#include <mission/devices/devicedefinitions/GomspaceDefinitions.h>

/**
 * @brief	This is the device handler class for all gomspace devices.
 *
 * @details	All gomspace devices are similar with respect to commanding. Thus
 * 			most of the functionality to command a gomspace device can be
 * 			accommodated in one class. For device specific functions, a new
 * 			class could be created by inheriting from the GomspaceDeviceHandler.
 */
class GomspaceDeviceHandler: public DeviceHandlerBase {
public:

	static const ReturnValue_t PACKET_TOO_LONG = MAKE_RETURN_CODE(0xE0);
	static const ReturnValue_t INVALID_TABLE_ID = MAKE_RETURN_CODE(0xE1);
	static const ReturnValue_t INVALID_ADDRESS = MAKE_RETURN_CODE(0xE2);
	static const ReturnValue_t INVALID_PARAM_SIZE = MAKE_RETURN_CODE(0xE3);
	static const ReturnValue_t INVALID_PAYLOAD_SIZE = MAKE_RETURN_CODE(0xE4);
	static const ReturnValue_t UNKNOWN_REPLY_ID = MAKE_RETURN_CODE(0xE5);

	/**
	 * @brief	Constructor
	 *
	 * @param maxConfigTableAddress	The maximum memory address of the configu-
	 * 								ration table of a gomspace device.
	 * @param maxHkTableAddress	The maximum memory address of a value in the
	 * 							houskeeping (telemetry) table of a gomspace
	 * 							device.
	 */
	GomspaceDeviceHandler(object_id_t objectId, object_id_t comIF,
	        CookieIF * comCookie, uint16_t maxConfigTableAddress, uint16_t maxHkTableAddress,
	        uint16_t hkTableReplySize, LocalPoolDataSetBase* hkTableDataset);
	virtual ~GomspaceDeviceHandler();

	/**
	 * @brief   This function can be used to set a gomspace device to normal mode immediately after
	 *          object creation.
	 */
	void setModeNormal();

protected:

	static const uint8_t MAX_PACKET_LEN = 36;
	static const uint8_t PARAM_SET_OK = 1;
	static const uint8_t PING_REPLY_SIZE = 2;
	static const uint8_t CONFIG_TABLE_ID = 1;
	static const uint8_t HK_TABLE_ID = 4;

	uint8_t rememberRequestedSize = 0;
	uint8_t rememberCommandId = GOMSPACE::NONE;
	uint8_t cspPacket[MAX_PACKET_LEN];

	uint16_t maxConfigTableAddress;
	uint16_t maxHkTableAddress;

	/** The size of the reply following a full hk table request.*/
	uint16_t hkTableReplySize;

	LocalPoolDataSetBase* hkTableDataset = nullptr;

	void doStartUp() override;
	void doShutDown() override;
	virtual ReturnValue_t buildNormalDeviceCommand(DeviceCommandId_t * id)
			override;
	ReturnValue_t buildTransitionDeviceCommand(DeviceCommandId_t * id) override;
	void fillCommandAndReplyMap() override;
	ReturnValue_t buildCommandFromCommand(DeviceCommandId_t deviceCommand,
				const uint8_t * commandData,size_t commandDataLen) override;
	ReturnValue_t scanForReply(const uint8_t *start, size_t remainingSize,
			DeviceCommandId_t *foundId, size_t *foundLen) override;
	ReturnValue_t interpretDeviceReply(DeviceCommandId_t id,
			const uint8_t *packet) override;
	void setNormalDatapoolEntriesInvalid() override;
	uint32_t getTransitionDelayMs(Mode_t modeFrom, Mode_t modeTo) override;
	/**
	 * @brief   The command to generate a request to receive the full housekeeping table is device
	 *          specific. Thus the child has to build this command.
	 */
	virtual ReturnValue_t generateRequestFullHkTableCmd(uint16_t hkTableSize);

	/**
	 * @brief	Because housekeeping tables are device specific the handling of the reply is
	 * 			given to the child class.
	 * @param id	The id of the command which initiates the full table request.
	 * @param packet	Pointer to the reply containing the hk table.
	 */
	virtual void letChildHandleHkReply(DeviceCommandId_t id, const uint8_t *packet) = 0;

	virtual LocalPoolDataSetBase* getDataSetHandle(sid_t sid) override;

private:

	/**
	 * @brief	Function to generate the command to set a parameter. Command
	 * 			will be sent to the ComIF over the rawPacket buffer.
	 */
	ReturnValue_t generateSetParamCommand(const uint8_t * commandData,
			size_t commandDataLen);

	/**
	 * @brief	Function to generate the command to get a parameter from a
	 * 			gomspace device. Command will be sent to the ComIF over the
	 * 			rawPacket buffer.
	 */
	ReturnValue_t generateGetParamCommand(const uint8_t * commandData,
			size_t commandDataLen);

	/**
	 * @brief	Function to generate the ping command for the ComIF.
	 */
	ReturnValue_t generatePingCommand(const uint8_t * commandData,
			size_t commandDataLen);

	/**
	 * @brief	Function to generate the command to reboot a gomspace device
	 * 			via the ComIF.
	 */
	void generateRebootCommand();

	/**
	 * @brief	Function to generate the command to force a ground watchdog
	 * 			reset in a gomspace device.
	 */
	ReturnValue_t generateResetWatchdogCmd();

};

#endif /* MISSION_DEVICES_GOMSPACEDEVICEHANDLER_H_ */