/* To programma auto ulopoiei tis kuries leitourgies
 * mias apla syndedemenhs listas pou apo8hkeuei xarakthres.
 */

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>

struct listNode{
	int id;
	char data;
	struct listNode* next;
};
typedef struct listNode node;

struct list{
	struct listNode* head;
	int size;
};
typedef struct list list;

/* Dhmiourgei mia nea lista kai epitrefei ena
 * pointer sth lista.
 */
list* newList(void){
	list* l;
	l = (list *) malloc(sizeof(list));
	l->head = NULL;
	l->size = 0;

	return l;
}

/* Diagrafei mia lista apeleu8erwnontas oles
 * 8eseis mnhmhs pou katalambanoun ta stoixeia ths listas.
 * Pairnei san orisma enan pointer sth lista pou 8a diagrapsei.
 */
void deleteList(list* l){
	node* curr = l->head;
	node* del;

	if(l->head == NULL);
	else{
		do{
			del=curr;
			curr=curr->next;
			free(del);
		}while(curr!=NULL);
	}
	free(l);

	return;
}

/* Eisagei ena neo stoixeio sth kefalh(head) mias listas.
 * Pairnei san orisma enan pointer sth lista pou 8a eisagoume to neo stoixeio,
 * to id pou einai to anagnwristiko tou neou stoixeiou kai to data pou einai ta 'dedomena'
 * tou neou stoixeiou.
 */
void insert(list* l, int id, char data){
	node* newnode;
	newnode = (node *) malloc(sizeof(node));
	newnode->id = id;
	newnode->data = data;

	if(l->head == NULL){
		l->head =  newnode;
	}

	else {
		newnode->next = l->head;
		l->head = newnode;
	}

	l->size++;
	return;
}

/* Diagrafei to stoixeio me anagnwristiko id.
 * Pairnei san orisma ena pointer sth lista apo thn opoia 8a diagrapsoume to stoixeio
 * kai epistrefei ton xarakthra pou perieixe to stoixeio auto.
 * An to stoixeio den bre8ei epistrefei ton Null character ('\0').
 */
char delete(list* l, int id){
	char ret;
	node *curr = l->head;
	node *prev = l->head;
	if(l->head == NULL) return '\0';
	else {

		do{
			if (curr->id == id){
				prev->next = curr->next;
				if(curr == l->head){
					l->head = curr->next;
				}
				ret = curr->data;
				free(curr);
				l->size--;

				return ret;
			}
			else {
				prev = curr;
				curr = curr->next;
			}
		}while(curr != NULL);
	}
	
	return '\0';
}

/* Anazhra to stoixeio me anagnwristiko id.
 * Pairnei san orisma ena pointer sth lista apo sthn opoia 8a anazhthsoume to stoixeio
 * kai epistrefei ton xarakthra pou periexei to stoixeio auto.
 * An to stoixeio den bre8ei epistrefei ton Null character ('\0').
 */
char lookUp(list *l,int id){
	node *curr = l->head;

	if(l->head == NULL) return '\0';
	else {

		do{
			if (curr->id == id){
				return curr->data;
			}
			else {
				curr = curr->next;
			}
		}while(curr != NULL);
	}
	
	return '\0';
}

/* Episterfei to mege8os mia listas.
 * Pairnei san orisma ena pointer sth lista.
 */
int size(list* l){
	return l->size;
}

/* Boh8htikh sunarthsh pou epistefei mhden (0) an h lista einai kenh h
 * ena (1) an h lista den einai kenh. H synarthsh eksetazei an h lista
 * einai kenh elegxontas an h kefalh(head) ths listas dixnei se NULL.
 * Pairnei ws orisma enan pointer sth lista pou 8a eksetasei
 */
int isEmpty(list* l){
	return (l->head == NULL);
}

/* Ektupwnei ena-ena ola ta stoixeia ths listas pou pairnei ws orisma
 */
void printList(list* l){
	node* curr=l->head;

	if(l->head == NULL){
		printf("Empty !\n");
	}

	while(curr != NULL){
		printf("Node-id: %d, data: %c\n",curr->id,curr->data);
		curr = curr->next;
	}
	return;
}

int main (void)
{
	list* mylist;
	char command, data;
	int id, go = 1;

	mylist = newList();

	printf("To insert a new node press I\nTo delete a node press D\nTo look up for a value press L\n\
To get the size of the list press S\nTo print the whole list press P\nTo quit press Q\n");
	
	while(go){
		printf("\nGive a command: ");
		scanf("%c",&command);

		switch (toupper(command)){
			case 'I':
				printf("Give the id and the character you want to insert in the list: ");
				scanf("%d %c",&id,&data);
				insert(mylist,id,data);
				break;
			case 'D':
				printf("Give the id of the node you want to delete: ");
				scanf("%d",&id);
				data = delete(mylist,id);
				if(!data)
					printf("The node with id %d is not in the list\n",id);
				else
					printf("Node deleted: id %d, data %c\n",id,data);
				break;
			case 'L':
				printf("Give the id of the node you want to look for: ");
				scanf("%d",&id);
				data = lookUp(mylist,id);
				if(!data)
					printf("The node with id %d is not in the list\n",id);
				else
					printf("Node found: id %d, data %c\n",id,data);
				break;
			case 'S':
				printf("List size: %d\n",size(mylist));
				break;
			case 'P':
				printList(mylist);
				break;
			case 'Q':
				deleteList(mylist);
				go = 0;
				break;
			default :
				printf("Please enter a valid command !\n");
				printf("To insert a new node press I\nTo delete a node press D\nTo look up for a value press L\n\
To get the size of the list press S\nTo quit press Q\n\n");
		}
		getchar();
	}

	return 0;
}
