#include <stdio.h> // Include stdio.h for basic functions
#include <string.h> // Include string.h for string functions
#include <ctype.h> // Include ctype.h for character analysis functions
#include <stdlib.h> // Include stdlib.h for exit()
#include <stdbool.h> // Include stdbool.h for booleans

#include "functions.h" // Include custom functions.h file

void PrintMenu() { // Function to print menu options
    printf("MENU\n"); // Print "MENU" header
    printf("c - Number of non-whitespace characters\n"); // Print 'c' option
    printf("w - Number of words\n"); // Print 'w' option
    printf("f - Fix capitalization\n"); // Print 'f' option
    printf("r - Replace all !'s\n"); // Print 'r' option
    printf("s - Shorten spaces\n"); // Print 's' option
    printf("q - Quit\n"); // Print 'q' option
    printf("\n"); // Print new line
}

char GetMenuInput() { // Function to get menu choice from user
    char menuInput; // Declare menuInput of type char
    printf("Choose an option:\n"); // Print choose prompt
    scanf(" %c", &menuInput); // Store user input for menuInput
    return menuInput; // Return menuInput
}

void ExecuteMenu(char menuInput, char userInputText[]) { // Function to execute other functions based on value of menuInput
    if (menuInput == 'c') { // If menuInput is 'c'
        printf("Number of non-whitespace characters: %d\n", GetChars(userInputText)); // Print output of GetChars()
        printf("\n"); // Print new line
    } else if (menuInput == 'w') { // If menuInput is 'w'
        printf("Number of words: %d\n", GetWords(userInputText)); // Print output of GetWords()
        printf("\n"); // Print new line
    } else if (menuInput == 'f') { // If menuInput is 'f'
        FixCapitals(userInputText); // Call FixCapitals() with argument userInputText
        printf("Edited text: %s\n", userInputText); // Print userInputText
    } else if (menuInput == 'r') { // If menuInput is 'r'
        ReplaceExclamation(userInputText); // Call ReplaceExclamation() with argument userInputText
        printf("Edited text: %s\n", userInputText); // Print userInputText
    } else if (menuInput == 's') { // If menuInput is 's'
        ShortenSpaces(userInputText); // Call ShortenSpaces() with argument userInputText
        printf("Edited text: %s\n", userInputText); // Print userInputText
    } else if (menuInput == 'q') { // If menuInput is 'q'
        exit(0); // Exit with code 0
    }
}

int GetChars(char userInputText[]) { // Function to count number of non-whitespace characters in userInputText
    int count = 0; // Declare and initialize count of type int as 0
    for (int i = 0; i < strlen(userInputText); ++i) { // For each i in userInputText
        if (!isspace(userInputText[i])) { // If userInputText at i is not whitespace
            ++count; // Increment count
        }
    }
    return count; // Return the value of count
}

int GetWords(char userInputText[]) { // Function to count number of words in userInputText
    int count = 0; // Declare and initialize count of type int as 0
    for (int i = 0; i < strlen(userInputText); ++i) { // For each i in userInputText
        if (count == 0) { // If count is 0
            if (isalpha(userInputText[i])) { // If userInputText at i is alpha
                ++count; // Increment count
            }
        } else { // If count is not 0
            if (isalpha(userInputText[i]) && isspace(userInputText[i - 1])) { // If userInputText at i is alpha and userInputText at i-1 is whitespace
                ++count; // Increment count
            }
        }
    }
    return count; // Return the value of count
}

void FixCapitals(char userInputText[]) { // Function to make letters at the beginning of each sentence capitals
    bool isFirstWord = true; // Declare and initialize isFirstWord of type bool as true
    for (int i = 0; i < strlen(userInputText); ++i) { // For each i in userInputText
        if (isFirstWord) { // If isFirstWord is true
            if (isalpha(userInputText[i])) { // If userInputText at i is alpha
                userInputText[i] = toupper(userInputText[i]); // Set userInputText at i to uppercase
                isFirstWord = false; // Set isFirstWord to false
            }
        } else { // If isFirstWord is false
            if (isalpha(userInputText[i]) && isspace(userInputText[i - 1]) && ((isspace(userInputText[i - 1]) && (userInputText[i - 2] == '.' || userInputText[i - 2] == '!' || userInputText[i - 2] == '?')) || (isspace(userInputText[i - 2]) && (userInputText[i - 3] == '.' || userInputText[i - 3] == '!' || userInputText[i - 3] == '?')))) { // If userInputText at i is alpha and userInputText at i-1 or i-2 is whitespace and userInputText at i-2 or i-3 is punctuation
                /*
                    Why take this absolutely horrid approach at determining the end of a sentence? Because none of the test cases or unit tests try to compare the output of FixCapitals with more than two spaces between words in a sample string.
                    It's far too much work to try and make this scalable when, ideally, ShortenSpaces() should be run prior to FixCapitals() anyway. But, that's not what the instructions say to do, so this is what we have instead.
                */
                userInputText[i] = toupper(userInputText[i]); // Set userInputText at i to uppercase
            }
        }
    }
}

void ReplaceExclamation(char userInputText[]) { // Function to replace all exclamation points with periods
    for (int i = 0; i < strlen(userInputText); ++i) { // For each i in userInputText
        if (userInputText[i] == '!') { // If userInputText at i is '!'
            userInputText[i] = '.'; // Set userInputText at i to '.'
        }
    }
}

void ShortenSpaces(char userInputText[]) { // Function to replace instances of double spaces with single spaces
    bool doubleSpacesRemaining = true; // Declare and initialize doubleSpacesRemaining of type bool as true
    int count = 0; // Declare and initialize count of type int as 0
    while (doubleSpacesRemaining) { // While doubleSpacesRemaining is true
        count = 0; // Initialize count as 0
        for (int i = 0; i < strlen(userInputText); ++i) { // For each i in userInputText
            if (isspace(userInputText[i]) && isspace(userInputText[i - 1])) {
                for (int j = i; j < strlen(userInputText); ++j) { // For each j in userInputText
                    userInputText[j] = userInputText[j + 1]; // Shift userInputText one to the left
                }
            }
        }
        for (int i = 0; i < strlen(userInputText); ++i) { // For each i in userInputText
            if (isspace(userInputText[i]) && isspace(userInputText[i - 1])) { // If there are still instances of double spaces
                ++count; // Increment count
            }
        }
        if (count <= 0) { // If count is less than or equal to 0
            doubleSpacesRemaining = false; // Set doubleSpacesRemaining to false
        }
    }
}