// Arup Guha
// 5/29/2020
// Code for Summer 2020 COP 3502 Section 18 Quiz

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#include "leak_detector_c.h"

// Struct for Part A
typedef struct item {
    char* name;
} item;

// Struct for Part B.
typedef struct charnode {
    char c;
    struct charnode* next;
} charnode;

charnode* makeLinkedList(char* word);
int countLowerCase(charnode* front);
void freeList(charnode* ptr);
void printString(charnode* ptr);


int main(void) {

    // So we can get the leak detector report.
    atexit(report_mem_leak);

    // Part A Question #1
    int* array = malloc(1000000*sizeof(int));
    for (int i=0; i<1000000; i++)
        array[i] = i;

    // Test to see array set to 0.
    for (int i=0; i<1000000; i++)
        if (array[i] != i)
            printf("Oops we messed up.\n");

    // Free this memory.
    free(array);

    // Part A Question #2 Given mallocs.
    int n;
    scanf("%d", &n);
    item* list = malloc(n*sizeof(item));

    for (int i=0; i<n; i++) {
       char temp[100];
       scanf("%s", temp);
       list[i].name = malloc((strlen(temp)+1)*sizeof(char));
       strcpy(list[i].name, temp);
    }

    // Part A Question #2 Solution - can be verified using leak detector.

    // First free each of the strings in the structs.
    for (int i=0; i<n; i++)
        free(list[i].name);

    // Now, free the array of item.
    free(list);


    /*** Part B tests starts here. ***/
    charnode* teststr = makeLinkedList("Hello, Fresh!");
    printString(teststr);
    printf("String has %d lower case letters.\n", countLowerCase(teststr));
    freeList(teststr);
    return 0;
}

// Solution to Part B Question #1
void printString(charnode* ptr) {

    // Go to end of string.
    while (ptr != NULL) {

        // Print this character.
        printf("%c", ptr->c);

        // Go to next.
        ptr = ptr->next;
    }

    // Add new line.
    printf("\n");
}

// Support code to test Part B questions
charnode* makeLinkedList(char* word) {

    int i = 0;

    // This is our list initially.
    charnode* front = NULL;
    charnode* back = NULL;

    // Go till null char.
    while (word[i] != '\0') {

        // Make the new node.
        charnode* tmp = malloc(sizeof(charnode));
        tmp->c = word[i];
        tmp->next = NULL;

        // All we have to do for first item.
        if (i == 0) {
            front = tmp;
            back = tmp;
        }

        // Patch old back to new back and update back.
        else {
            back->next = tmp;
            back = tmp;
        }

        // Go to next character in the word.
        i++;
    }

    // This is our pointer.
    return front;
}

// Solution to Part B Question #2
int countLowerCase(charnode* front) {

    // Store answer here.
    int res = 0;

    // Go through whole list.
    while (front != NULL) {

        // Add 1 if this is a lower case character.
        if (islower(front->c))
            res++;

        // Go to next character.
        front = front->next;
    }

    // Value to return.
    return res;
}

// Frees all the memory for the linked list pointed to by ptr.
void freeList(charnode* ptr) {
    if (ptr != NULL) {
        freeList(ptr->next);
        free(ptr);
    }
}
