/*----------------------------------- LIST.C ---------------------------------------------------------
  -  AUTHOR:  Steven P. Silvey																		 -
  -  DATE CREATED:  2/7/2004																		 -
  -  DATE MODIFIED: 4/15/2005																		 -
  -  PURPOSE:  This file contains any function pertainning to the list structure.					 -
  -    *MODIFICATION (4/15/2005) - Added Sort_List to sort the list efficiently						 -
  ----------------------------------------------------------------------------------------------------*/

#ifndef _LIST_CPP_
#define _LIST_CPP_

#include "list.h"
//#include "comerr.h"
#include<iostream>

/*************************************************************************************************
*										CONSTRUCTORS											 *
*************************************************************************************************/
/*  PURPOSE:  To create the LIST structure which connects information together in a list.
	PARAMETERS:  NONE
	RETURN:  The newly dynamically allocated LIST structure.				*/
LIST *Create_List()
{
	LIST *temp;

	temp = (LIST *) malloc(sizeof(LIST));

	if(!temp) return NULL;

	//temp->ckey = (char *) malloc(30 * sizeof(char));
	strcpy(temp->ckey, "");
	temp->ikey = 0;
	temp->ikey2 = 0;
	temp->data = NULL;
	temp->next = NULL;

	return temp;
}

/*  PURPOSE:  To copy a List item and return it with out it's link connections
	PARAMETERS:  copy - the node being copied
	RETURN:  The copied node															*/
LIST *Copy_List(LIST *copy)
{
	LIST *temp;
	
	temp = (LIST *) malloc(sizeof(LIST));

	if(!temp) return NULL;

	//temp->ckey = new char[strlen(copy->ckey) + 1];	
	strcpy(temp->ckey, copy->ckey);
	temp->ikey = copy->ikey;
	temp->ikey2 = copy->ikey2;
	temp->data = copy->data;
	temp->next = copy->next;
	//temp->next = NULL;

	return temp;
}


/*************************************************************************************************
*										DESTRUCTORS												 *
*************************************************************************************************/
/*  PURPOSE:  To free an entire linked list
	PARAMETERS:  traverse - the list to destroy
	RETURN:  NONE																		*/	
void Destroy_List(LIST *traverse)
{
	LIST *old = traverse;

	if(traverse == NULL)
		return;
	
	while(traverse != NULL)
	{
		traverse = traverse->next;
		free(old);
		old = traverse;
	}
}

/*************************************************************************************************
*										 DISPLAYERS												 *
*************************************************************************************************/
/*  PURPOSE:  To display all the information of one list structure to the specified output 
			  direction.
	PARAMETERS:  display - the list structure to display
				 fdir - the direction of output for the display to take place
	RETURN:  NONE																		*/
void Display_List_Item(LIST *display, FILE *fdir)
{

	fprintf(fdir, "List Display:\n");
	if(display == NULL)
	{
		fprintf(fdir, "List is NULL");
		return;
	}	
	fprintf(fdir, "  iKey:  %d\n", display->ikey);
	fprintf(fdir, "  cKey:  %s\n", display->ckey);
	
	if(display->next == NULL)
		fprintf(fdir,"  Link: NONE\n");
	else
		fprintf(fdir,"  Link: %d\n", display->next->ikey);

	if(display->data == NULL)
		fprintf(fdir, "  Data: NONE\n\n");
	else
		fprintf(fdir, "  Data: YES\n\n");

}

/*  PURPOSE:  To display all the information of one list structure to the monitor.
	PARAMETERS:  display - the list structure to display
	RETURN:  NONE																		*/
void Display_List_Item(LIST *display)
{
	Display_List_Item(display, stdout);
}

/*  PURPOSE:  To display all the information of an entire list to the specified direction of
			  output.
	PARAMETERS:  begin - the first item in the entire list
				 fdir - the direction of output for the display to take place
	RETURN:  NONE																		*/
void Display_List(LIST *begin, FILE *fdir)
{
	LIST *traverse = begin;
	int lcount = 0;

	if(traverse == NULL)
	{
		fprintf(fdir, "List is NULL");
		return;
	}

	while(traverse != NULL)
	{
		lcount++;
		Display_List_Item(traverse, fdir);
		fprintf(fdir, "\n");
		traverse = traverse->next;		
	}
	fprintf(fdir, "LIST COUNT: %d\n", lcount);
}

/*  PURPOSE:  To display all the information of an entire list to the monitor.			  
	PARAMETERS:  begin - the first item in the entire list				 
	RETURN:  NONE																		*/
void Display_List(LIST *begin)
{
	Display_List(begin, stdout);
}





/*************************************************************************************************
*										  MUTATORS												 *
*************************************************************************************************/
/*  PURPOSE:  To add a premade LIST item to a linked list
	PARAMETERS:  traverse - the list to add to				 
				 add - the item to add
	RETURN:  The new updated list														*/	
LIST *Add_List(LIST *Begin, LIST *Item)
{
	LIST *traverse = Begin, *Add = Copy_List(Item);
		
	while(traverse != NULL && traverse->next != NULL)
		traverse = traverse->next;
		
	
	if(Begin == NULL)
		Begin = Add;
	else
		traverse->next = Add;
	
	return Begin;
}



/*  PURPOSE:  To add an item to a linked list 
	PARAMETERS:  traverse - the list to add to
				 data - the item to add to the list
				 ID - the quickinfo index of the new list element
	RETURN:  The new updated list														*/	
LIST *Add_List(LIST *traverse, void *data, int ID)
{
	LIST *Begin = traverse;
	LIST *Add;
	while(traverse != NULL && traverse->next != NULL)
		traverse = traverse->next;

	Add = Create_List();
	Add->data = data;
	Add->ikey = ID;
	Add->next = NULL;
	if(traverse == NULL)
		Begin = Add;
	else
		traverse->next = Add;

	return Begin;
}

/*  PURPOSE:  To add an item to a linked list (with char ID)
	PARAMETERS:  traverse - the list to add to
				 data - the item to add to the list
				 cID - the quickinfo index of the new list element
	RETURN:  The new updated list														*/	
LIST *Add_List(LIST *traverse, void *data, char *cID)
{
	LIST *Begin = traverse;
	LIST *Add;
	while(traverse != NULL && traverse->next != NULL)
		traverse = traverse->next;

	Add = Create_List();
	Add->data = data;
	strcpy(Add->ckey, cID);
	Add->next = NULL;
	if(traverse == NULL)
		Begin = Add;
	else
		traverse->next = Add;

	return Begin;
}


/*  PURPOSE:  To search for an item in a list based on an index
	PARAMETERS:  traverse - the list to search through
	             ID - the string to look for
	RETURN:  The LIST node that contains the cID.  NULL if no node found.				*/
LIST *Search_List(LIST *traverse, int iID)
{
	while(traverse != NULL && traverse->ikey != iID)
		traverse = traverse->next;

	return traverse;
}


/*  PURPOSE:  To search for an item in a list based on a string
	PARAMETERS:  traverse - the list to search through
	             cID - the string to look for
	RETURN:  The LIST node that contains the cID.  NULL if no node found.				*/
LIST *Search_List(LIST *traverse, const char *cID)
{
	while(traverse != NULL && strcmp(traverse->ckey, cID) != 0)
		traverse = traverse->next;

	return traverse;
}

/*  PURPOSE:  To sort the list by its ikey value in ascending order
	PARAMETERS:  begin - the list to sort
	RETURN:  The sorted LIST															*/
LIST *Sort_List(LIST *begin)
{
	LIST *traverse = begin;
	LIST *fix;

	while(traverse != NULL && traverse->next != NULL)
	{
		if(traverse->next != NULL && traverse->next->ikey < traverse->ikey)
		{
			fix = traverse->next;
			traverse->next = fix->next;
			begin = Fix_List(begin, fix);
		}
		else
			traverse = traverse->next;
	}	

	return begin;
}

/* PURPOSE:  To take a node that's out of place and put it in its correct location
   PARAMETERS:  begin - the list we are sorting
				fix - the node that is out of place
   RETURN:  The "more" sorted list														*/
LIST *Fix_List(LIST *begin, LIST *fix)
{
	LIST *traverse = begin;

	while(traverse != NULL && traverse->next != NULL && traverse->next->ikey < fix->ikey)
		traverse = traverse->next;

	if(fix->ikey < begin->ikey)
	{
		fix->next = begin;
		begin = fix;
	}
	else
	{
		fix->next = traverse->next;
		traverse->next = fix;
	}

	return begin;
}


#endif /* End of _LIST_CPP_ */

