#include <stdlib.h>
#include <stdio.h>
#include "liss_list.h"

// creates a new empty list
list newList()
{
	list l = malloc(sizeof(listst));
	l -> size = 0;
	l -> head = NULL;
	l -> last = NULL;

	return l;
}

// creates a new list with the values that are in array
list newInitList(elem array[], int dim)
{
	int i;
	list l = newList();

	for (i=0; i<dim; i++)
		addElemList(array[i], l);
	
	return l;
}

// creates a new node with value=var and next=null and returns a pointer to the node
link newNodeList(elem val)
{
	link lnode = malloc(sizeof(listNode));
	lnode -> value = val;
	lnode -> next = NULL;

	return lnode;
}

// adds a node, referenced by pointer lnode, in the last position of list l
void addNodeList(link lnode, list l)
{
	if (isEmptyList(l))
	{
		l -> head = lnode;
		l -> last = lnode;	
	}
	else
	{
		l -> last -> next = lnode;
		l -> last = lnode;
	}
	(l -> size)++;
}

// adds element val to the last position of list l
void addElemList(elem val, list l)
{
	link lnode;

	lnode = newNodeList(val);
	addNodeList(lnode, l);
}

// returns the size of list l
int getSizeList(list l)
{
	return l -> size;
}

// returns the element of the node in the position pos
elem getElemList(int pos, list l)
{
	int i;
	link aux = l -> head;

	if((getSizeList(l) - 1) < pos)
	{
		printf("Sequence index out of bounds");
		exit(1);
	}
	else
		for (i=0; i<pos; i++)
			aux = aux -> next;

	return aux -> value;
}

// prints in stdout the list l
void printList(list l)
{
	link aux = l -> head;

	while (aux != NULL)
	{
		printf("%d\n", aux -> value);
		aux = aux -> next;
	}
}

// returns the first element of list l
elem getHeadList(list l)
{
	if(isEmptyList(l))
	{
		printf("Sequence is empty!");
		exit(1);
	}
	
	return l -> head -> value;
}

// returns a new list containing the tail (all elements except the first one) of list l
list getTailList(list l)
{
	list auxlist = newList();
	list newlist = newList();

	auxlist -> head = l -> head -> next;
	auxlist -> last = l -> last;
	(auxlist -> size)--;

	copyList(auxlist, newlist);

	free(auxlist);

	return newlist;
}

// creates a new list l_dest equal to list l_orig
void copyList(list l_orig, list l_dest)
{
	link aux = l_orig -> head;
	elem val;

	cleanList(l_dest->head);
	l_dest -> size = 0;
	l_dest -> head = NULL;
	l_dest -> last = NULL;
	
	while (aux != NULL)
	{
		val = aux -> value;
		addElemList(val, l_dest);
		aux = aux -> next;
	}
}

// cleans the list from node nd till the end
void cleanList(link nd)
{
	if (nd != NULL)
	{
		cleanList(nd->next);
		free(nd);
		nd = NULL;
	}
}

// checks if list l is empty
int isEmptyList(list l)
{
	if ((l -> head == NULL) && (l -> last == NULL) && (l -> size == 0))
		return 1;
	else
		return 0;
}

// checks if element val belongs to list l
int isMemberList(elem val, list l)
{
	link aux = l -> head;
	int res = 0;

	while ((aux != NULL) && (!res))
	{
		if (aux -> value == val)
			res = 1;
		aux = aux -> next;
	}
	return res;
}

// removes the first node with element val in list l
void remElemList(elem val, list l)
{
	link aux = l -> head, del = NULL;
	int found = 0;
	
	if ( (l -> head -> value) == val )
	{
		del = l -> head;
		l -> head = l -> head -> next;
		del -> next = NULL;
		(l -> size)--;
		found = 1;
		free(del);
	}

	while ((aux != NULL) && (!found))
	{
		if ( (aux -> next -> value) == val)
		{
			del = aux -> next;
			aux -> next = aux -> next -> next;
			del -> next = NULL;
			(l -> size)--;
			found = 1;
			free(del);
		}
		aux = aux -> next;
	}
}
