/* CS107 Pig Latin Example
 * Code by Nick Troccoli and Lisa Yan
 * 
 * This program converts text to pig latin as an example of
 * how to use dynamic memory allocation on the heap with malloc
 * and free.
 *
 * If there are no additional command-line arguments, the program
 * prints out tests of converting individual words to pig latin.
 * If there are additional command-line arguments, the program
 * converts each argument to pig latin and prints out each one.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <assert.h>

#define LOWERCASE_VOWELS "aeiou"
#define LOWERCASE_ALPHABET "abcdefghijklmnopqrstuvwxyz"


/* Function: pig_way
 * --------------------------
 * This function performs the "way" case of pig latin on the in string, 
 * storing the output in the out buffer.  The "way" case is where we copy in
 * the original word and append "way".
 */
void pig_way(char *out, const char *in) {
    strcpy(out, in);
    strcat(out, "way");
}

/* Function: pig_regular
 * --------------------------
 * This function performs the "regular" case of pig latin on the in string, 
 * storing the output in the out buffer.  The "regular" case is where we move
 * all initial consonants to the end of the word and append "ay".
 */
void pig_regular(char *out, const char *in) {
    int n = strcspn(in, LOWERCASE_VOWELS);
    strcpy(out, in + n);
    strncat(out, in, n);
    strcat(out, "ay");
}

/* Function: pig_latin
 * --------------------------
 * This function returns a pig-latinified version of the in string.
 * It is the caller's responsibility to free the returned string,
 * which is allocated on the heap.
 * Simplified pig latin rules are:
 * - if the word starts with a vowel, append "way"
 * - otherwise, move all initial consonants to the end, and append "ay"
 *
 * This function assumes that the provided word is lowercase.
 * If the word begins with non-alphabetic characters, this function returns NULL.
 */
char *pig_latin(const char *in) {
    // If the word starts with non-alphabetic characters, we can't translate
    if (strcspn(in, LOWERCASE_ALPHABET) > 0) {
        return NULL;
    }

    char *out = NULL;

    // If the word starts with a vowel, add "way"
    if (strchr(LOWERCASE_VOWELS, in[0]) != NULL) {
        int out_len = strlen(in) + strlen("way");
        out = malloc(sizeof(char) * (out_len + 1)); // null terminator
        assert(out != NULL);

        pig_way(out, in);
    } else {
        // Otherwise, move all initial consonants to the end, and append "ay"
        int out_len = strlen(in) + strlen("ay");
        out = malloc(sizeof(char) * (out_len + 1));
        assert(out != NULL);

        pig_regular(out, in);
    }

    return out;
}

/************************************ main ************************************/

/* Function: test_pig_latin
 * --------------------------
 * This function runs test cases on pig_latin for the specified individual words,
 * and prints out the result for each.
 */
void test_pig_latin(char *words[], int num_words) {
    for (int i = 0; i < num_words; i++) {
        char *pig_word = pig_latin(words[i]);
        // NOTE: doesn't check if word is untranslateable (see lab3 for more!)
        printf("%s -> %s\n", words[i], pig_word);
        free(pig_word);
    }
}

int main(int argc, char *argv[]) {
    if (argc == 1) {
        // Test translating individual words
        char *testing[] = {
            "pig",
            "simple",
            "party",
            "omelet",
            "explain",
            "anteater",
            "grouchy",
            "desk"
        };

        int n_elems = sizeof(testing) / sizeof(char *);
        test_pig_latin(testing, n_elems);
    } else {
        // Test translating the command line arguments
        test_pig_latin(argv + 1, argc - 1);
    }

    return 0;
}
