/** @brief Enumeration of Error Codes
 *
 * @copyright 2020 Remsdaq Ltd.
 * @file c4_error_codes.h
 *
 * @date 20 May 2020
 * @author Dan Smithers <dwhs@remsdaq.com>
 *
 */


#ifndef C4_ERROR_CODES_H_
#define C4_ERROR_CODES_H_

/*******************************************************************************
 * Includes
 ******************************************************************************/

#include "c4_colours.h"
#include <stdbool.h>

/*******************************************************************************
 * Defines
 ******************************************************************************/
/** @def CALLISTO_ERR
 * @brief X-Macro to construct error codes, printable strings, and flash codes.
 *
 * @param name Error ID
 * @param text Printable string
 * @param col_code Array containing LED colour and flash code.
 */
/** @brief Error codes and strings.
 *
 * The macro values are used to construct matching enumeration and string array
 * using the x-macro strategy.
 */
#define ERROR_LIST \
    CALLISTO_ERR(OK, \
                 "Success.", \
                 {E_RED,      DI, DAH,   0,   0,   0}) \
    CALLISTO_ERR(FILE_NOT_FOUND, \
                 "File not found or not readable.", \
                 {E_GREEN,    DI, DAH, DAH, DAH, DAH}) \
    CALLISTO_ERR(FIELD_NOT_FOUND, \
                 "Field not found in file.", \
                 {E_GREEN,    DI,  DI, DAH, DAH, DAH}) \
    CALLISTO_ERR(VERSION, \
                 "Incompatible version.", \
                 {E_GREEN,    DI,  DI,  DI, DAH, DAH}) \
    CALLISTO_ERR(SYNTAX, \
                 "Bad syntax.", \
                 {E_GREEN,    DI,  DI,  DI,  DI, DAH}) \
    CALLISTO_ERR(FIELD_UNDEFINED, \
                 "Undefined field found in config.", \
                 {E_GREEN,    DI,  DI,  DI,  DI, DIT}) \
    CALLISTO_ERR(NOT_IMPLEMENTED, \
                 "Feature not implemented.", \
                 {E_YELLOW,   DI,  DI,  DI,  DI, DIT}) \
    CALLISTO_ERR(UNINITIALISED, \
                 "Subsystem not initialised.", \
                 {E_YELLOW,  DAH,  DI,  DI,  DI, DIT}) \
    CALLISTO_ERR(FAILED, \
                 "Operation failed.", \
                 {E_YELLOW,  DAH, DAH,  DI,  DI, DIT}) \
    CALLISTO_ERR(ALREADY_SET, \
                 "Write-once value already set.", \
                 {E_YELLOW,  DAH, DAH, DAH,  DI, DIT}) \
    CALLISTO_ERR(HARDWARE, \
                 "Hardware error.", \
                 {E_CYAN,    DAH,  DI,  DI,  DI, DIT}) \
    CALLISTO_ERR(RANGE, \
                 "Range error.", \
                 {E_CYAN,    DAH, DAH,  DI,  DI, DIT}) \
    CALLISTO_ERR(IMAGE_INCOMPATIBLE, \
                 "Application image is not compatible.", \
                 {E_MAGENTA,  DI, DAH, DAH, DAH, DAH}) \
    CALLISTO_ERR(IMAGE_CORRUPT, \
                 "Application image is corrupt.", \
                 {E_MAGENTA,  DI,  DI, DAH, DAH, DAH}) \
    CALLISTO_ERR(IMAGE_BOOTABLE, \
                 "Application image is bootable.", \
                 {E_MAGENTA,  DI,  DI,  DI, DAH, DAH}) \
    CALLISTO_ERR(IMAGE_EXECUTABLE, \
                 "Application image is executable.", \
                 {E_MAGENTA,  DI,  DI,  DI,  DI, DAH}) \
    CALLISTO_ERR(SOCKET, \
                 "LWIP socket error.", \
                 {E_BLUE,     DI,  DI,  DI,  DI, DIT})

/*******************************************************************************
 * Structures
 ******************************************************************************/

/*******************************************************************************
 * Prototypes
 ******************************************************************************/

/** @brief Enumeration of error codes. */
typedef enum {
#define CALLISTO_ERR(name, text, col_code ...) C4_ERR_##name,
    ERROR_LIST
#undef CALLISTO_ERR
    C4_ERR_MAX
} exit_code_t;


/** @brief Print exit code on serial line and flash led.
 *
 * This function will enter a continuous loop if fatal is true and anything other than C4_ERR_OK is sent.
 *
 * @param[in] text Optional user text to display.
 * @param[in] errVal Exit code.
 * @param[in] fatal If true this error is fatal and the code loops forever.
 *
 */
void C4_displayError(const char *text, exit_code_t errVal, bool fatal);

/*******************************************************************************
 * Variables
 ******************************************************************************/

#endif /* C4_ERROR_CODES_H_ */
