#ifndef _SANITYCHECK_H_
#define _SANITYCHECK_H_

// Utility macros for handling quotes
#define Q(x) #x
#define QUOTE(x) Q(x)

// Utility macros for checking string lengths
#define STRING_LENGTH_CHECK(str, max_length) (sizeof(str) <= (max_length) + 1)
#define IS_ALPHANUMERIC(c) ((((c) >= '0') && ((c) <= '9')) || (((c) >= 'A') && ((c) <= 'Z')) || (((c) >= 'a') && ((c) <= 'z')))
#define IS_PRINTABLE_ASCII(c) ((c) >= 32 && (c) <= 126)
#define IS_VALID_WIFI_CHAR(c) (IS_PRINTABLE_ASCII(c))
#define IS_ALPHANUMERIC_HELPER(str, i) (i >= sizeof(str) - 1 || IS_ALPHANUMERIC(str[i]))
#define IS_PRINTABLE_ASCII_HELPER(str, i) (i >= sizeof(str) - 1 || IS_PRINTABLE_ASCII(str[i]))
#define IS_VALID_WIFI_CHAR_HELPER(str, i) (i >= sizeof(str) - 1 || IS_VALID_WIFI_CHAR(str[i]))
#define IS_ALPHANUMERIC_IMPL(str, i) (IS_ALPHANUMERIC_HELPER(str, i) && IS_ALPHANUMERIC_HELPER(str, i+1) && IS_ALPHANUMERIC_HELPER(str, i+2) && IS_ALPHANUMERIC_HELPER(str, i+3) && IS_ALPHANUMERIC_HELPER(str, i+4) && IS_ALPHANUMERIC_HELPER(str, i+5) && IS_ALPHANUMERIC_HELPER(str, i+6) && IS_ALPHANUMERIC_HELPER(str, i+7) && IS_ALPHANUMERIC_HELPER(str, i+8) && IS_ALPHANUMERIC_HELPER(str, i+9) && IS_ALPHANUMERIC_HELPER(str, i+10) && IS_ALPHANUMERIC_HELPER(str, i+11) && IS_ALPHANUMERIC_HELPER(str, i+12) && IS_ALPHANUMERIC_HELPER(str, i+13) && IS_ALPHANUMERIC_HELPER(str, i+14) && IS_ALPHANUMERIC_HELPER(str, i+15) && IS_ALPHANUMERIC_HELPER(str, i+16))
#define IS_PRINTABLE_ASCII_IMPL(str, i) (IS_PRINTABLE_ASCII_HELPER(str, i) && IS_PRINTABLE_ASCII_HELPER(str, i+1) && IS_PRINTABLE_ASCII_HELPER(str, i+2) && IS_PRINTABLE_ASCII_HELPER(str, i+3) && IS_PRINTABLE_ASCII_HELPER(str, i+4) && IS_PRINTABLE_ASCII_HELPER(str, i+5) && IS_PRINTABLE_ASCII_HELPER(str, i+6) && IS_PRINTABLE_ASCII_HELPER(str, i+7) && IS_PRINTABLE_ASCII_HELPER(str, i+8) && IS_PRINTABLE_ASCII_HELPER(str, i+9) && IS_PRINTABLE_ASCII_HELPER(str, i+10) && IS_PRINTABLE_ASCII_HELPER(str, i+11) && IS_PRINTABLE_ASCII_HELPER(str, i+12) && IS_PRINTABLE_ASCII_HELPER(str, i+13) && IS_PRINTABLE_ASCII_HELPER(str, i+14) && IS_PRINTABLE_ASCII_HELPER(str, i+15) && IS_PRINTABLE_ASCII_HELPER(str, i+16) && IS_PRINTABLE_ASCII_HELPER(str, i+17) && IS_PRINTABLE_ASCII_HELPER(str, i+18) && IS_PRINTABLE_ASCII_HELPER(str, i+19) && IS_PRINTABLE_ASCII_HELPER(str, i+20) && IS_PRINTABLE_ASCII_HELPER(str, i+21) && IS_PRINTABLE_ASCII_HELPER(str, i+22) && IS_PRINTABLE_ASCII_HELPER(str, i+23) && IS_PRINTABLE_ASCII_HELPER(str, i+24))
#define IS_ALPHANUMERIC_STRING(str) (IS_ALPHANUMERIC_IMPL(str, 0))
#define IS_PRINTABLE_ASCII_STRING(str) (IS_PRINTABLE_ASCII_IMPL(str, 0))
#define IS_VALID_WIFI_STRING(str) (IS_VALID_WIFI_CHAR_HELPER(str, 0) && IS_VALID_WIFI_CHAR_HELPER(str, 1) && IS_VALID_WIFI_CHAR_HELPER(str, 2) && IS_VALID_WIFI_CHAR_HELPER(str, 3) && IS_VALID_WIFI_CHAR_HELPER(str, 4) && IS_VALID_WIFI_CHAR_HELPER(str, 5) && IS_VALID_WIFI_CHAR_HELPER(str, 6) && IS_VALID_WIFI_CHAR_HELPER(str, 7) && IS_VALID_WIFI_CHAR_HELPER(str, 8) && IS_VALID_WIFI_CHAR_HELPER(str, 9) && IS_VALID_WIFI_CHAR_HELPER(str, 10) && IS_VALID_WIFI_CHAR_HELPER(str, 11) && IS_VALID_WIFI_CHAR_HELPER(str, 12) && IS_VALID_WIFI_CHAR_HELPER(str, 13) && IS_VALID_WIFI_CHAR_HELPER(str, 14) && IS_VALID_WIFI_CHAR_HELPER(str, 15) && IS_VALID_WIFI_CHAR_HELPER(str, 16) && IS_VALID_WIFI_CHAR_HELPER(str, 17) && IS_VALID_WIFI_CHAR_HELPER(str, 18) && IS_VALID_WIFI_CHAR_HELPER(str, 19) && IS_VALID_WIFI_CHAR_HELPER(str, 20) && IS_VALID_WIFI_CHAR_HELPER(str, 21) && IS_VALID_WIFI_CHAR_HELPER(str, 22) && IS_VALID_WIFI_CHAR_HELPER(str, 23) && IS_VALID_WIFI_CHAR_HELPER(str, 24) && IS_VALID_WIFI_CHAR_HELPER(str, 25) && IS_VALID_WIFI_CHAR_HELPER(str, 26) && IS_VALID_WIFI_CHAR_HELPER(str, 27) && IS_VALID_WIFI_CHAR_HELPER(str, 28) && IS_VALID_WIFI_CHAR_HELPER(str, 29) && IS_VALID_WIFI_CHAR_HELPER(str, 30) && IS_VALID_WIFI_CHAR_HELPER(str, 31) && IS_VALID_WIFI_CHAR_HELPER(str, 32))

// ADMIN_PASSWORD check
#ifndef ADMIN_PASSWORD
    #error "You need to define ADMIN_PASSWORD for OTA-Update"
#else
    _Static_assert(STRING_LENGTH_CHECK(QUOTE(ADMIN_PASSWORD), 16), "ADMIN_PASSWORD must be at most 16 characters long");
#endif

// WIFI_AP_SSID check
#ifndef WIFI_AP_SSID
    #warning "No WIFI_AP_SSID defined. Using DeviceName"
    #define WIFI_AP_SSID DEVICE_NAME
#else
    _Static_assert(STRING_LENGTH_CHECK(QUOTE(WIFI_AP_SSID), 32), "WIFI_AP_SSID must be at most 32 characters long");
    _Static_assert(IS_VALID_WIFI_STRING(QUOTE(WIFI_AP_SSID)), "WIFI_AP_SSID must contain only valid WiFi characters");
#endif

// WIFI_PASS_SEED check
#ifndef WIFI_PASS_SEED
    #error "You must define an WIFI_PASS_SEED for Standalone AP-Mode"
#else
    _Static_assert(STRING_LENGTH_CHECK(QUOTE(WIFI_PASS_SEED), 16), "WIFI_PASS_SEED must be at most 16 characters long");
    _Static_assert(IS_ALPHANUMERIC_STRING(QUOTE(WIFI_PASS_SEED)), "WIFI_PASS_SEED must contain only alphanumeric characters (a-z, A-Z, 0-9)");
#endif

// DEVICE_NAME check
#ifndef DEVICE_NAME
    #error "You must define DEVICE_NAME"
#else
    _Static_assert(STRING_LENGTH_CHECK(QUOTE(DEVICE_NAME), 24), "DEVICE_NAME must be at most 24 characters long");
    _Static_assert(IS_VALID_WIFI_STRING(QUOTE(DEVICE_NAME)), "DEVICE_NAME must contain only valid WiFi characters");
#endif

// Mutual exclusion check for LoRa features
#if defined(FEATURE_ENABLE_UARTLORA) && defined(FEATURE_ENABLE_LORA)
    #error "You cannot enable LoRa and UART-Protocol at the same time!"
#endif

// WIFI_CLIENT checks
#ifdef FEATURE_ENABLE_WIFI_CLIENT
    #ifndef WIFI_PASSWORD_CLIENT
        #error "You must define an WIFI_PASSWORD_CLIENT for OTA-Update"
    #else
        _Static_assert(STRING_LENGTH_CHECK(QUOTE(WIFI_PASSWORD_CLIENT), 63), "WIFI_PASSWORD_CLIENT must be at most 63 characters long");
    #endif

    #ifndef WIFI_SSID_CLIENT
        #error "You must define an WIFI_SSID_CLIENT for OTA-Update"
    #else
        _Static_assert(STRING_LENGTH_CHECK(QUOTE(WIFI_SSID_CLIENT), 32), "WIFI_SSID_CLIENT must be at most 32 characters long");
        _Static_assert(IS_VALID_WIFI_STRING(QUOTE(WIFI_SSID_CLIENT)), "WIFI_SSID_CLIENT must contain only valid WiFi characters");
    #endif
#endif

#endif // _SANITYCHECK_H_
