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

#define go(ptr) ptr=ptr->next

//building structure
struct data {
	int num;
	char *name;//name ptr
	float gpa;
	struct data *next;
};

typedef struct data student;

//header initialize
student *header = NULL;

//printing functions
void printInstr() {
	printf("DATABASE PROGRAM\nuse i, u, d, D, f, l to run\n");
}
void printArrow() {
	printf("==>");
}

//basis funtions
student* lastNode() {
	student *last;
	for (last=header;last->next!=NULL;go(last));
	return last;
}//returtn last node
int lengthName(char *name_s) {
	int i;
	for (i=0;*(name_s+i)!='\0';i++);
	return i;
}
void insertHeader (int num_s, char *name_s, float gpa_s) {
	student *newNode;
	newNode=(student *)malloc(sizeof(student));

	if (header == NULL) {
		newNode -> next=NULL;
		header=newNode;
	}//no nodes in list
	else {
		newNode->next=header;
		header=newNode;
	}//building a link
	newNode -> num=num_s;
	newNode -> name=(char*)malloc(sizeof(char)*(lengthName(name_s)+1));
	strcpy(newNode->name,name_s);
	newNode -> gpa=gpa_s;
}
void insertNew (student *node, int num_s, char *name_s, float gpa_s) {
	student *newNode;
	newNode=(student *)malloc(sizeof(student));

	if (node == NULL) {
		newNode->next = NULL;
		node = newNode;
	}//'node' is NULL
	else {		
			newNode->next=node->next;
			node->next=newNode;
		}
	newNode -> num=num_s;
	newNode -> name=(char*)malloc(sizeof(char)*(lengthName(name_s)+1));
	strcpy(newNode->name,name_s);//copy name
	newNode -> gpa=gpa_s;
}
void printNode (student *node) {
	printf("NUM: %5d  NAME: %10s  GPA: %.2f\n",node->num,node->name,node->gpa);
}


//funtions
void printList() {
	student *curr=header; student *prev=header;
	int i,j;
	if (header==NULL) { printArrow(); printf("NO node in List..\n"); }//no nodes in List
	else { printArrow(); printf("Nodes in the List..\n");
	for (i=0;curr!=NULL;i++)
		go(curr); //determine size of List
	curr=header;
	for(;i>0;i--) {
		for(j=1;j<i;go(curr),j++);
		printNode(curr);
		curr=header;
	}//double loop to access nodes reversly
	}
}
void insertStudent(int num_s, char *name_s, float gpa_s) {
	student *prev=header; student *curr=header;
	int rpt=0;//to check error;repeated number..
	
	if (header==NULL) insertHeader(num_s, name_s, gpa_s);//empty list
	else {
		for(prev=header;prev!=NULL;go(prev)) {
			if(prev->num==num_s) rpt++;
		}
		if (rpt!=0) {printArrow(); printf("No.%d is already in List..\n",num_s); }
		else {
		if (header->next==NULL) {
		if (header->num<num_s) insertHeader(num_s, name_s, gpa_s);
		else insertNew(header, num_s, name_s, gpa_s);
	} //only one node on list
	else {
		if (header->num<num_s) insertHeader(num_s, name_s, gpa_s);
		else {
		while (curr->num>num_s&&curr!=NULL) {
			prev=curr;
			go(curr);
		}
		insertNew(prev, num_s, name_s, gpa_s);//insert new node
		}}}}
}
void deleteStudent(int num_s) {
	student *prev; student *curr;
	prev=header; curr=header;

	if (header==NULL) { printArrow(); printf("NO node in List..\n"); }
	else if (header->next==NULL&&header->num==num_s) {
		printArrow(); printf("%d %s %.2f has been eliminated..\n"
			,header->num,header->name,header->gpa);
		free(header->name);
		go(header);
		free(prev);//header is 'only' node in List
		header=NULL;//after touching 'header', initialize for safety..
	}
	else if (header->num==num_s&&header->next!=NULL) {
		printArrow(); printf("%d %s %.2f has been eliminated..\n"
			,header->num,header->name,header->gpa);
		free(header->name);
		go(header);//manipulate header forward
		free(prev);//free header
	}
	else {	go(curr);		
		while (curr!=NULL) {
			if (curr->num==num_s) break;
			
			prev=curr;
			go(curr);//go next
		}
		if (curr==NULL) {printArrow(); printf("NO No.%d in the List..\n",num_s);}//no num_s in List
		else {
			printArrow(); printf("%d %s %.2f has been eliminated..\n",curr->num,curr->name,curr->gpa);
			free(curr->name);
			prev->next=curr->next;
			free(curr);//delete node and reserve link between nodes..
		}
	}
}//to delete node and announcement
void clearNode(int num_s) {
	student *prev; student *curr;
	prev=header; curr=header; go(curr);

	if (header==NULL);
	else if (header->num==num_s) {

		free(header->name);
		go(header);
		free(prev);//free header
	}
	else {
		while (curr!=NULL) {
			if (curr->num==num_s) break;
			
			prev=curr;
			go(curr);//go next
		}
		if (curr==NULL);
		else {
			free(curr->name);
			prev->next=curr->next;
			free(curr);//delete nodes..
		}
	}
}//clear node without annoucement
void findStudent(int num_s) {
	student *curr=header;
	if (header==NULL) { printArrow(); printf("NO node in List..\n"); }//empty list
	else {
		while (curr!=NULL) {
			if (curr->num==num_s) break;//break after find num_s

			go(curr);//go next
		}

		if (curr==NULL) { printArrow(); printf("NO No.%d in the List..\n",num_s); }
		else printNode(curr);
	}
}
void updateStudent(int num_s, char *name_s, float gpa_s) {
	student *curr=header; student *prev=header;
	if (header==NULL) { printArrow(); printf("NO node in List..\n"); }//empty list
	else {
		if (header->num==num_s) {
		clearNode(num_s);
		insertHeader(num_s,name_s,gpa_s);//header was only node and header->num==num_s..
		}
		else {

		while (curr!=NULL) {
			if (curr->num==num_s) break;

			prev=curr;
			go(curr);//go next
		}
		if (curr==NULL) { printf("NO No.%d in the List..\n",num_s); }
		else {
			
		clearNode(num_s);
		insertNew(prev,num_s,name_s,gpa_s);
			
		}}}
	}
void deleteAll() {
	student *prev=header; student *curr=header;
	printArrow(); printf("Delete every node\n");
		
	if (header==NULL) {/*do nothing*/}//no node in List
	else {
		if (header->next == NULL) { //only one node in List
			free(header->name);
			free(header);
			header=NULL;//initialize header to avoid error..
		}
		else {
			go(curr);
						
			while(curr!=NULL) {
				free(curr->name);//free name
				free(prev);//free node

				prev=curr;
				go(curr);
			}
			free(prev);//delete last node
			header=NULL;//initialize to avoid error..
		}}
}

int main () {
	char instr;
	char name_s[10];
	int num_s;
	float gpa_s;

	printInstr();

	while (instr!='q') {
		fflush(stdin);
		scanf("%c",&instr);

		switch (instr) {
		case 'i' :
			scanf("%d %s %f",&num_s,name_s,&gpa_s);
			insertStudent(num_s, name_s, gpa_s);
			//insert node
			break;
		case 'u' :
			scanf("%d %s %f",&num_s,name_s,&gpa_s);
			//update
			updateStudent(num_s,name_s,gpa_s);
			break;
		case 'f' :
			scanf("%d",&num_s);
			findStudent(num_s);
			//find
			break;
		case 'd' :
			scanf("%d",&num_s);
			deleteStudent(num_s);
			//delete one
			break;
		case 'D' :
			deleteAll();
			//delete all
			break;
		case 'l' :
			printList();
			break;
		case 'q' :
			printArrow();
			printf("Good bye..\n");
		}
	}

	return 0;
}