#ifndef SCATTERWEB_INTERNAL_H_
#define SCATTERWEB_INTERNAL_H_

/// Header for serial transmission of binary commands
typedef struct cmd_serial_header {
	uint8_t					marker;
	uint8_t					size;
	uint8_t					protocol;
	uint8_t					reserved;
	uint8_t					destination;
} cmd_serial_header_t;

/**
 * @brief	Unsafe version of cmd_args
 * @internal
 */
struct cmd_args_unsafe {
	const cmd_header_t (*	request);
	const char*					args;				///< pointer to command arguments
	uint16_t				arg_size;			///< size of command arguments
	cmd_header_t*			response;
	char(*				response_args);		///< pointer to buffer for command response
	uint16_t				response_bufsize;
	//void(*)(void*)			fpSendAsyncResponse,
};

#define CMD_ASCII_NAME_OFFSET			(sizeof(cmd_header_t) - sizeof(struct cmd_binid))
#define CMD_ASCII_MAX_HEADER_LENGTH		(CMD_ASCII_NAME_OFFSET + CMD_ASCII_MAX_NAME_LENGTH + 1)

#define CMD_IS_ASCII(cmd)				((cmd->flags & CMD_REQFLAG_ASCII) == CMD_REQFLAG_ASCII)
#define CMD_IS_BINARY(cmd)				((cmd->flags & CMD_REQFLAG_ASCII) == 0)

extern char	reply_buffer[1][TERM_BUFSIZE + sizeof(cmd_header_t) + 1];

/// Get handler function for a command
command_t* _Cmd_GetHandler(const uint8_t flags, const void* id);

/// handle a command request from the radio interface
void _Cmd_RadioRequest(struct netpacket_handler_args* args);

/// handle an incoming reply from the radio interface
void _Cmd_RadioReply(struct netpacket_handler_args* args);

/// forward a command through the radio interface
void _Cmd_Forward(
	const netaddr_t*			pDestination,
	const cmd_header_t (*const	pCmd),
	const void*					data,
	const uint8_t				dataLength
);

/// handle an incoming ascii mode command request from the serial interface
uint16_t _Cmd_AsciiSerialRequest(char* line);

/// handle an incoming binary mode command request from the serial interface
uint16_t _Cmd_BinarySerialRequest(
	cmd_serial_header_t*	sh,
	bool					ascii_interface,
	cmd_header_t*			header,
	uint16_t				headerlength,
	char*					args
);

/// helper function for _Cmd_BinPrintReply#
void _Cmd_BinSerialWrite(const void (*const data), const uint16_t numchars);

/// print a binary mode command reply to the serial interface
void _Cmd_BinPrintReply(
	const netaddr_t* source,
	const uint16_t size,
	const cmd_header_t (*const header)
);

/// generate a command header from an ascii mode command request
uint16_t _Cmd_AsciiHeaderFromLine(void* buffer, char** data);

/// print an ascii mode command reply to the serial interface
void _Cmd_AsciiPrintReply(
		const netaddr_t*			pSource,
		const uint16_t				size,
		const cmd_header_t (*const 	header)
);

uint16_t _Cmd_GetHeaderSize(const cmd_header_t (*const	pCmd));

/// claim a reply buffer
char* _Cmd_GetBuffer();

/// free a reply buffer
void _Cmd_FreeBuffer(char* buffer);

/// generate status message reply
void _Cmd_StateReply(cmd_header_t* buffer, uint8_t state);

/// test if a character is valid for a command name
bool _Cmd_IsValidNameChar(char c);

uint16_t _Cmd_GetAscCmdArgs(const cmd_header_t (*const header), char** args);

enum cmd_l2protocols {
	CMD_PROTOCOL_NONE,
	CMD_PROTOCOL_SYSINFO,
	CMD_PROTOCOL_ACMDREQUEST,
	CMD_PROTOCOL_ACMDRESPONSE,
	CMD_PROTOCOL_BCMDREQUEST,
	CMD_PROTOCOL_BCMDRESPONSE,
	CMD_PROTOCOL_LOG
};

#if CMD_ENABLE_LOGGING
/// generate Debuglog printouts
void _Cmd_logCommand(
	char type,
	const netaddr_t (*const		pAdr),
	const cmd_header_t (*const	pCmd),
	uint16_t size
);
#endif

#endif /*SCATTERWEB_INTERNAL_H_*/
