#include "header.h"

void readFromKeyboard(Element_t *item)
{
    if (!item)
    {
        fprintf(stderr, "Nullpointer in readFromKeyboard()\n");
        return;
    }
    fprintf(stdout, "Enter song title: ");
    fgets(item->songtitle,255,stdin);
   *strrchr(item->songtitle,'\n')=0;
    while (getchar() != '\n') {}

    fgets(item->interpreter,255,stdin);
   *strrchr(item->interpreter,'\n')=0;
    while (getchar() != '\n') {}
}

Element_t *allocateElement()
{
    Element_t *new = 0;
    if (!(new = malloc(sizeof(Element_t))))
    {
        fprintf(stderr, "Memory allocation error in allocateElement()");
        exit(-1);
    }
    readFromKeyboard(new);
    new->next = 0;
    return new;
}

Element_t *insertLast(Element_t *list)
{
    Element_t *new = allocateElement();
    if (!list)
    {
        return new;
    }
    Element_t *last = list;

    while(last->next)
        last = last->next;
    last->next = new;
    return list;
}

void freeList(Element_t **list)
{
    if (!list)
    {
        fprintf(stderr, "Nullpointer in freeList()");
        exit(-1);
    }
    Element_t *next;
    while(*list)
    {
        next = list[0]->next;
        free(list[0]);
        list[0] = next;
    }
    list[0] = 0;
}

void print_singleElement(Element_t *element)
{
    if (element)
    {
        fprintf(stdout, "begin-elem--------------------\n");
        fprintf(stdout, "%s\t%s\n", element->songtitle, element->interpreter);
        fprintf(stdout, "end-elem----------------------\n");
    }
    else
    {
        fprintf(stdout, "Nullpointer!\n");
    }
}

void print_entireList(Element_t *list)
{
    while(list)
    {
        fprintf(stdout, "%s\t%s\n", list->songtitle, list->interpreter);
        list = list->next;
    }
}

void print_list_reverse(Element_t *list)
{
    if (list->next)
        print_list_reverse(list->next);
    fprintf(stdout, "%s\t%s\n", list->songtitle, list->interpreter);
}

Element_t *elementAt(Element_t *list, long index)
{
    if (index == 0) return list;
    long counter = 0;
    while(list->next)
    {
        list = list->next;
        if (++counter == index) return list;
    }
    return 0;
}

long elementsCount(Element_t *list)
{
    if (!list) return 0;
    long counter = 1;
    while(list->next)
    {
        list = list->next;
        counter++;
    }
    return counter;
}

Element_t *removeFirst(Element_t *list)
{
    Element_t *temp = list->next;
    free(list);
    return temp;
}

void insertAt(Element_t *list, long insertAfter)
{
    Element_t *new = insertLast(0);
    Element_t *at = elementAt(list, insertAfter);
    new->next = at->next;
    at->next = new;
}

void print_list_random(Element_t *list)
{
    if (list->next)
    {
        if (rand() < 16383)
        {
            print_list_random(list->next);
            fprintf(stdout, "%s\t%s\n", list->songtitle, list->interpreter);
        }
        else
        {
            fprintf(stdout, "%s\t%s\n", list->songtitle, list->interpreter);
            print_list_random(list->next);
        }
    }
    else
    {
        fprintf(stdout, "%s\t%s\n", list->songtitle, list->interpreter);
    }
}

void sort_list(Element_t **list)
{
    Element_t *temp = *list;
    Element_t *prev;
    long i, j;
    for (j = elementsCount(*list) - 1; j > 0; j--)
    {
        i = 0;
        prev = 0;
        temp = *list;
        while (i < j)
        {
            //printf("\n%ld %ld\t%s\t%s", j, i, temp->songtitle, (temp->next)->songtitle);
            if (strcmp(temp->songtitle, (temp->next)->songtitle) > 0)
            {
                //printf("\tswap");
                Element_t *swap = temp->next;
                temp->next = swap->next;
                swap->next = temp;
                if (prev)
                    prev->next = swap;
                else
                    *list = swap;
                prev = swap;
            }
            else
            {
                prev = temp;
                temp = temp->next;
            }
            i++;
        }
        //printf("\n");
        //print_entireList(*list);
    }
}


int main()
{
    srand(time(0));
    Element_t *list = malloc(sizeof(Element_t));
    strcpy(list->songtitle, "I am First!");
    strcpy(list->interpreter, "Hello there.");
    list->next = 0;
    Element_t *last = list;
    long i;
    for (i = 0; i < 11; i++)
    {
        Element_t *new;
        new = malloc(sizeof(Element_t));
        new->songtitle[0] = i + 'A';
        new->interpreter[0] = i+ 'a';
        new->next = 0;
        last->next = new;
        last = new;
    }
    print_entireList(list);
    printf("\n");


    printf("Reverse Print\n");
    print_list_reverse(list);
    printf("\n");
    printf("Single Element at NOElems - 4\n");
    print_singleElement(elementAt(list, elementsCount(list)-4));
    printf("\n");
    printf("Remove First\n");
    list = removeFirst(list);
    print_entireList(list);
    printf("\n");
    printf("Insert At 4\n");
    insertAt(list, 4);
    print_entireList(list);
    printf("\n");
    printf("Random Print\n");
    print_list_random(list);
    printf("\n");
    printf("Sort\n");
    sort_list(&list);
    print_entireList(list);
    printf("\n");

    freeList(&list);
    return 0;
}