//
// chainedlist.cpp
//
// chained lists management
//
// g2d library
//
// loïc berthelot, 2004
// based on scol language 2d library
//

#include <windows.h>
#include "x/scolplugin.h"
#include "./chainedlist.h"


 
//*****************************************
//
// ObjChainedList Constructor
//
//*****************************************
//
void chainedlist_init (ObjChainedList* o)
{
//
#if DEBUG_LIB2DOS
MMechostr (0, "ObjChainedList::ObjChainedList");
#endif
//

  o->begin = NULL;
  o->end   = NULL;
  o->size  = 0;
}





//*****************************************
//
// ObjChainedList add
//
//*****************************************
//
int chainedlist_add (ObjChainedList* o, int id, int type, void* item)
{
ChainedList* tmp;

//
#if DEBUG_LIB2DOS
MMechostr (0, "ObjChainedList::add %d  %d", (int)o->begin, (int)item);
#endif
//

    tmp = (ChainedList*) malloc (sizeof(ChainedList));

	tmp->id = id;
	tmp->type = type;

	tmp->item = item;
 

	tmp->nxt  = NULL;

	if (o->end == NULL)
	{
		o->begin = tmp;
		o->end   = o->begin;
	}
	else
	{
		o->end->nxt = tmp;
		o->end = o->end->nxt;
	}

	o->size++;

	return o->size; 
}




void* chainedlist_retreive (ObjChainedList* o, int id, int* type)
{
ChainedList* tmp = o->begin;
ChainedList* father = NULL;

//
#if DEBUG_LIB2DOS
MMechostr (0, "ObjChainedList::retreive %d  %d", (int)o->begin, (int)id);
#endif
//

	while ((tmp != NULL) && (tmp->id != id))
	{
		father = tmp;
		tmp = tmp->nxt;
	}


	// not found
	if (tmp == NULL) 
	{
		return NULL;
	}

    *type = tmp->type;
	return tmp->item;
}



//*****************************************
//
// ObjChainedList remove
//
//*****************************************
//
int chainedlist_remove (ObjChainedList* o, int id)
{
ChainedList* tmp = o->begin;
ChainedList* father = NULL;

//
#if DEBUG_LIB2DOS
MMechostr (0, "ObjChainedList::remove %d  %d", (int)o->begin, (int)id);
#endif
//

	while ((tmp != NULL) && (tmp->id != id))
	{
		father = tmp;
		tmp = tmp->nxt;
	}

	// not found
	if (tmp == NULL) return (-1);

	// item found. it's the first of the list
	if (father == NULL)
	{
		o->begin = tmp->nxt;
		free (tmp);
		o->size--;
		if (o->size == 0) o->end = NULL;
		return o->size;
	}

	// check if it's the last one
	if (o->end->id == id) o->end = father;

	// item found. it's the not the first of the list
	father->nxt = tmp->nxt;
	free (tmp);
	o->size--;
	return o->size;
}
 


//*****************************************
//
// ObjChainedList destroy
//
//*****************************************
//
void chainedlist_destroy (ObjChainedList* o)
{
ChainedList* tmp = o->begin;
ChainedList* elem = NULL;

//
#if DEBUG_LIB2DOS
MMechostr (0, "ObjChainedList::destroy %d", (int)o->begin);
#endif
//

	while (tmp != NULL)
	{
		elem = tmp;
		tmp = tmp->nxt;
		free (elem);
	}

	o->begin = NULL;
	o->end   = NULL;
	o->size = 0;
}


//*****************************************
//
// ObjChainedList enum
//
//*****************************************
//
int chainedlist_enumItems (ObjChainedList* o, void(* callback)(void*,void*), void* param)
{
ChainedList* tmp = o->begin;


//
#if DEBUG_LIB2DOS
MMechostr (0, "ObjChainedList::enumItems %d  %d", (int)o->begin, (int)callback);
#endif
//

	while (tmp != NULL)
	{
		callback (tmp->item, param);
		tmp = tmp->nxt;
	}
	return 1;
}




//*****************************************
//
// ObjChainedList sort
//
//*****************************************
//
int chainedlist_sort (ObjChainedList* o, int type)
{
ChainedList* list = o->begin;
ChainedList* tmp = (ChainedList*) malloc (sizeof(ChainedList));
int i;

//
#if DEBUG_LIB2DOS
MMechostr (0, "ObjChainedList::sort %d  %d", (int)o->begin, type);
#endif
//


	for (i=0; i < o->size + 1; i++)
	{

	list = o->begin;

	while (list->nxt != NULL)
	{
		if (stricmp ((char*)list->item, (char*)((ChainedList*)list->nxt)->item) < 0)
		{
			tmp->item = list->item;
			tmp->id = list->id;
			tmp->type = list->type;

			list->item = ((ChainedList*)list->nxt)->item;
			list->id = ((ChainedList*)list->nxt)->id;
			list->type = ((ChainedList*)list->nxt)->type;

			((ChainedList*)list->nxt)->item = tmp->item;
			((ChainedList*)list->nxt)->id = tmp->id;
			((ChainedList*)list->nxt)->type = tmp->type;
		}

		list = list->nxt;
	}
	}

	free (tmp);

	return 1;
}




int  chainedlist_getSize (ObjChainedList* o) 
{
	return o->size;
}