/*
 * list_manipulation.cpp: Functions that manipulate the list of entries
 * 
 * @author: Alexander Mikroyannidis
 * web site: http://www.geocities.com/alexmikro
 * e-mail: alexmikro@hotmail.com
 *
 */

#include <stdio.h>
#include <string.h>
#include <malloc.h>
#include <stdlib.h>
#include "agenda_server.h"

entry_pointer find_entry(entry_pointer ptr, char *pattern);
entry_pointer insert_entry(entry_pointer &headPtr, diary_entry new_entry);
entry_pointer remove_entry(entry_pointer &headPtr, entry_pointer ptr);
int save_list(entry_pointer ptr, char *filename);
int load_list(entry_pointer &headPtr, char *filename);
entry_pointer find_last(entry_pointer ptr);
void destroy_list(entry_pointer &ptr);

extern int error_type;


entry_pointer find_entry(entry_pointer ptr, char *pattern){

	while(ptr!=NULL){
		if(_strnicmp(ptr->last_name, pattern, strlen(pattern))==0)
			return ptr;
		ptr=ptr->next;
	}
	return NULL;
}



entry_pointer insert_entry(entry_pointer &headPtr, diary_entry new_entry){

	entry_pointer ptr, tempPtr;

	// Creation of new entry:
	ptr=(entry_pointer)malloc(sizeof(diary_entry));
	if(ptr==NULL) return NULL;
	strcpy(ptr->first_name, new_entry.first_name);
	strcpy(ptr->last_name, new_entry.last_name);
	strcpy(ptr->email, new_entry.email);
	strcpy(ptr->phone, new_entry.phone);

	// The case when headPtr has to change:
	if((headPtr==NULL)||(stricmp(headPtr->last_name, ptr->last_name)>0)){
		ptr->previous=NULL;
		ptr->next=headPtr;
		if(headPtr!=NULL) headPtr->previous=ptr;
		headPtr=ptr;
		return ptr;
	}

	// The case when the new entry has to be put somewhere 
	// between the first and the last entry of the list:
	tempPtr=headPtr->next;
	while(tempPtr!=NULL){
		if(stricmp(tempPtr->last_name, ptr->last_name)>0){
			(tempPtr->previous)->next=ptr;
			ptr->previous=tempPtr->previous;
			ptr->next=tempPtr;
			tempPtr->previous=ptr;
			return ptr;
		}
		tempPtr=tempPtr->next;
	}

	// The case when the new entry has to be the last one in the list:
	tempPtr=find_last(headPtr);
	tempPtr->next=ptr;
	ptr->previous=tempPtr;
	ptr->next=NULL;
	return ptr;
}



entry_pointer remove_entry(entry_pointer &headPtr, entry_pointer ptr){

	entry_pointer tempPtr;

	if(headPtr==ptr){
		if(headPtr->next==NULL)
			headPtr=NULL;
		else {
			headPtr=headPtr->next;
			headPtr->previous=NULL;
		}
	}
	else{
		(ptr->previous)->next=ptr->next;
		if(ptr->next!=NULL) (ptr->next)->previous=ptr->previous;
	}

	if(ptr->next==NULL) tempPtr=headPtr;
	else tempPtr=ptr->next;

	free((void*)ptr);
	return tempPtr;
}



int save_list(entry_pointer ptr, char *filename){

	FILE *fp;

	fp=fopen(filename, "w");
	if(fp==NULL) return -1;

	while(ptr!=NULL){
		fprintf(fp, "%s%s%s%s\n", ptr->first_name, ptr->last_name, ptr->email, ptr->phone);
		ptr=ptr->next;
	}
	fclose(fp);
	return 0;
}


int load_list(entry_pointer &headPtr, char *filename){

	FILE *fp;
	diary_entry new_entry;
	char line[100];

	fp=fopen(filename, "r");
	if(fp==NULL){
		error_type=OPEN_FILE_ERR;
		return -1;
	}

	destroy_list(headPtr); // frees the memory occupied by the old list

	while(!feof(fp)){
		if(fgets(line, 100, fp)==NULL){
			if(ferror(fp)){
				error_type=READ_FILE_ERR;
				return -1;
			}
		}
		else{
			strncpy(new_entry.first_name, line, 20);
			strncpy(new_entry.last_name, line+20, 20);
			strncpy(new_entry.email, line+40, 40);
			strncpy(new_entry.phone, line+80, 15);
			new_entry.first_name[20]='\0';
			new_entry.last_name[20]='\0';
			new_entry.email[40]='\0';
			new_entry.phone[15]='\0';
			if(insert_entry(headPtr, new_entry)==NULL){
				error_type=INSERT_ENTRY_ERR;
				return -1;
			}
		}
	}
	fclose(fp);
	return 0;
}
		

entry_pointer find_last(entry_pointer ptr){

	while(ptr->next!=NULL)
		ptr=ptr->next;

	return ptr;
}


void destroy_list(entry_pointer &ptr){

	entry_pointer tempPtr;

	while(ptr!=NULL){
		tempPtr=ptr->next;
		free((void*)ptr);
		ptr=tempPtr;
	}
}






