/** \file
 *  \brief This file defines the interface to a simple serial debug console and command interpreter.
 *
 *  \note As always, <project.h> and <CONFIG.h> should be included <I>before</I> this file.
 */

#ifndef COMM_CONSOLE_H
#define COMM_CONSOLE_H

#ifdef __cplusplus
extern "C" {
#endif

/* Include Files */

/* Preprocessor and Type Definitions */
    
#define COMM_CONSOLE_TASK_STACK_SIZE_in_bytes   512

#define COMM_Console_PutChar     UART_and_BLE_PutChar
#define COMM_Console_PutString   UART_and_BLE_PutString

#define COMM_CONSOLE_COMMAND_MAX_LENGTH 50

//! Character signifying the end of a console message.
#define COMM_CONSOLE_END_OF_MESSAGE ('\n')

//! Character used between parameters in a console message.
#define COMM_CONSOLE_PARAMETER_DELIMITER (' ')

//! Character signifying the end of a string.
#define COMM_CONSOLE_STRING_TERMINATOR ('\0')

//! Result of executing a console command callback.
typedef enum
{
    COMM_CONSOLE_CMD_RESULT_UNKNOWN = 0,
    COMM_CONSOLE_CMD_RESULT_SUCCESS = 1,
    COMM_CONSOLE_CMD_RESULT_PARAMETER_ERROR = 2
} COMM_Console_Command_Result_T;

//! Result of parsing a console command parameter.
typedef enum
{
    COMM_CONSOLE_PARAMETER_RESULT_UNKNOWN = 0,
    COMM_CONSOLE_PARAMETER_RESULT_SUCCESS = 1,
    COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_ERROR = 2,
    COMM_CONSOLE_PARAMETER_RESULT_PARAMETER_END = 3
} COMM_Console_Parameter_Result_T;

//! Prototype of a console command callback.
/*! 
 *  \ingroup CONSOLE
 *  All console commands must use this signature.
 *
 *  \param[in]   data   Pointer to the string containg the console command (and any arguments).
 *  \param[in]   size   Size (in char8) of the data string.
 *  \return             #COMM_CONSOLE_CMD_RESULT_SUCCESS on success
 *  \return             #COMM_Console_Command_Result_T otherwise
 */
typedef COMM_Console_Command_Result_T (* const COMM_Console_Command_Handler_T)(char8 * data, uint32_t size);

typedef struct
{
    const char8 * const Command_Name;
    const char8 * const Help;
    COMM_Console_Command_Handler_T Execute_Command;
} COMM_Console_Command_Table_Entry_T;

/* Public Variables */

//! Handle of the COMM_Console_Task() given when the task was created.
extern TaskHandle_t COMM_Console_Task_Handle;

/* Public Functions */

void COMM_Console_Init(void);
void COMM_Console_Task(void * pvParameters);
void COMM_Console_Execute_Internal_Command(const uint8_t * const command);
void COMM_Console_Print_String(const char8 * const text);
void COMM_Console_Print_UInt32(uint32_t value);
void COMM_Console_Print_SInt32(int32_t value);
void COMM_Console_Print_UInt32AsHex(uint32_t value);
void COMM_Console_Print_UInt64(uint64_t value);
void COMM_Console_Print_UInt64AsHex(uint64_t value);
void COMM_Console_Print_Float(float value);

void COMM_Console_ByteToHex(char8 * buffer, uint8_t byte);

/* Inline Functions */

//! Prints an 8-bit unsigned integer to the serial console.
inline void COMM_Console_Print_UInt8(uint8_t value)
{
    COMM_Console_Print_UInt32((uint32_t) value);
}

//! Prints an 8-bit unsigned integer to the serial console using a hexadecimal representation.
inline void COMM_Console_Print_UInt8AsHex(uint8_t value)
{
    COMM_Console_Print_UInt32AsHex((uint32_t) value);
}

//! Prints an 8-bit signed integer to the serial console.
inline void COMM_Console_Print_Int8(int8_t value)
{
    COMM_Console_Print_SInt32((int32_t) value);
}

//! Prints a 16-bit unsigned integer to the serial console.
inline void COMM_Console_Print_UInt16(uint16_t value)
{
    COMM_Console_Print_UInt32((uint32_t) value);
}

//! Prints a 16-bit unsigned integer to the serial console using a hexadecimal representation.
inline void COMM_Console_Print_UInt16AsHex(uint16_t value)
{
    COMM_Console_Print_UInt32AsHex((uint32_t) value);
}

//! Prints a 16-bit signed integer to the serial console.
inline void COMM_Console_Print_Int16(int16_t value)
{
    COMM_Console_Print_SInt32((int32_t) value);
}

static inline void UART_and_BLE_PutChar(uint8 txDataByte)
{    
    UART_Console_Put(txDataByte); 
    COMM_BLE_UART_PutChar(txDataByte);
}

static inline void UART_and_BLE_PutString(const char8 string[])
{
    UART_Console_PutString(string);
    COMM_BLE_UART_PutString(string, strlen(string));
}

#ifdef __cplusplus
}
#endif

#endif // COMM_CONSOLE_H
