#include "utilities.h"

/**
 * @brief Validates whether a given string contains only characters allowed in WiFi SSIDs and passwords.
 *
 * This function checks each character in the provided string to ensure
 * that it contains only characters allowed in WiFi SSIDs and passwords.
 * It considers characters from 'A' to 'Z', 'a' to 'z', '0' to '9', as well as
 * the following special characters: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
 *
 * @param string Pointer to the string to be validated.
 * @param size Size of the string including the null-terminator.
 * @return true if the string contains only allowed characters or is NULL,
 *         false otherwise.
 */
bool validateWiFiString(char *string, size_t size)
{
    if (string == NULL)
        return false;

    for (size_t i = 0; i < size; i++)
    {
        char c = string[i];
        if (c == '\0')
        {
            // Reached the end of the string, all characters were valid WiFi characters.
            return true;
        }
        if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
              (c >= '0' && c <= '9') || c == '!' || c == '"' || c == '#' ||
              c == '$' || c == '%' || c == '&' || c == '\'' || c == '(' ||
              c == ')' || c == '*' || c == '+' || c == ',' || c == '-' ||
              c == '.' || c == '/' || c == ':' || c == ';' || c == '<' ||
              c == '=' || c == '>' || c == '?' || c == '@' || c == '[' ||
              c == '\\' || c == ']' || c == '^' || c == '_' || c == '`' ||
              c == '{' || c == '|' || c == '}' || c == '~' || c == ' '))
        {
            // Found a character that is not a valid WiFi character.
            return false;
        }
    }
    // If the loop completes without finding a null terminator, the string is invalid.
    return false;
}

/**
 * @brief Copies a string to a buffer, replacing invalid WiFi SSID characters with a placeholder.
 *
 * This function checks each character in the provided input string to ensure
 * that it contains only characters allowed in WiFi SSIDs and passwords. If a character
 * is invalid, it replaces it with a placeholder character (e.g., '_').
 * It considers characters from 'A' to 'Z', 'a' to 'z', '0' to '9', as well as
 * the following special characters: ! " # $ % & ' ( ) * + , - . / : ; < = > ? @ [ \ ] ^ _ ` { | } ~
 *
 * @param input Pointer to the input string to be validated and copied.
 * @param buffer Pointer to the buffer where the output string will be copied.
 * @param bufferSize Size of the buffer including the null-terminator.
 */
void sanitizeWiFiString(const char *input, char *buffer, size_t bufferSize)
{
    if (input == NULL || buffer == NULL || bufferSize == 0)
        return;

    size_t i;
    for (i = 0; i < bufferSize - 1; i++) // Leave space for null-terminator
    {
        char c = input[i];
        if (c == '\0')
        {
            // Reached the end of the input string, terminate the buffer
            buffer[i] = '\0';
            return;
        }
        if (!((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') ||
              (c >= '0' && c <= '9') || c == '!' || c == '"' || c == '#' ||
              c == '$' || c == '%' || c == '&' || c == '\'' || c == '(' ||
              c == ')' || c == '*' || c == '+' || c == ',' || c == '-' ||
              c == '.' || c == '/' || c == ':' || c == ';' || c == '<' ||
              c == '=' || c == '>' || c == '?' || c == '@' || c == '[' ||
              c == '\\' || c == ']' || c == '^' || c == '_' || c == '`' ||
              c == '{' || c == '|' || c == '}' || c == '~' || c == ' '))
        {
            // Replace invalid character with placeholder
            buffer[i] = '_';
        }
        else
        {
            // Copy valid character to buffer
            buffer[i] = c;
        }
    }
    // Null-terminate the buffer
    buffer[i] = '\0';
}

/**
 * @brief Generates a device-specific password based on a seed and the ESP8266 Chip ID.
 *
 * This function combines a given seed with the unique Chip ID of the ESP8266 device to create a device-specific password.
 * The resulting password is stored in the provided character buffer.
 *
 * @param seed The seed string used for password generation. Should be up to 16 characters long.
 * @param passwordBuffer The character buffer where the generated password will be stored.
 * @param bufferLength The length of the password buffer. Should be large enough to hold the generated password and null terminator.
 */
void GenerateDeviceSpecificPassword(const char* seed, char* passwordBuffer, size_t bufferLength) {
    uint32_t chipId = ESP.getChipId();
    char chipIdStr[9]; // 8 characters + null terminator
    snprintf(chipIdStr, sizeof(chipIdStr), "%08X", chipId);

    char combined[33]; // seed (16) + chipId (8) + null terminator (1)
    strncpy(combined, seed, 16);
    strncat(combined, chipIdStr, 8);

    // Simple hash function for demonstration
    unsigned long hash = 5381;
    int c;
    char *str = combined;

    while ((c = *str++)) {
        hash = ((hash << 5) + hash) + c; // hash * 33 + c
    }

    snprintf(passwordBuffer, bufferLength, "%08X%08X", hash, hash);
    passwordBuffer[bufferLength - 1] = '\0'; // Ensure null termination
}