function joChainedListClass (parent_obj)
{
	this.parent						= parent_obj;
	this.element_first			= null;
	this.element_last				= null;
	
	this.GetElementCount		= _joChain_GetElementCount;
	this.GetElementPosition 	= _joChain_GetElementPosition;
	
	this.GetElement 				= _joChain_GetElement;
	this.AppendElement			= _joChain_AppendElement;
	this.RemoveElement			= _joChain_RemoveElement;
	this.RemoveAllElements		= _joChain_RemoveAllElements;
	this.SwapElements 			= _joChain_SwapElements;
	this.MoveElementToEnd		= _joChain_MoveElementToEnd;
	this.MoveElementToStart	= _joChain_MoveElementToStart;
	this.CopyElements				= _joChain_CopyElements;
}

/* ********************************************************************************************************** */

function _joChain_CopyElements (source_chain)
{
	if (source_chain)
	{
		var source_element = source_chain.element_first;
		var new_element;
		while (source_element)
		{
			new_element = source_element.CopyNode (this);
			this.AppendElement (new_element);
		
			source_element = source_element.element_next;
		}
		
	}
}

/* ********************************************************************************************************** */

function _joChain_GetElement (obj_index)
{
	var result = null;
	var position = 0;
	var obj = this.element_first;
	
	while (!result && obj)
	{
		if (position == obj_index)
		{
			result = obj;
		}
		else
		{
			position++;
			obj = obj.element_next;
		}
	}
	return result;
}

/* ********************************************************************************************************** */

function _joChain_GetElementPosition (chain_obj)
{
	var result = -1;
	var position = 0;
	var obj = this.element_first;
	
	while (result < 0 && obj)
	{
		if (obj == chain_obj)
		{
			result = position;
		}
		else
		{
			position++;
			obj = obj.element_next;
		}
	}
	return result;
}

/* ********************************************************************************************************** */

function _joChain_GetElementCount()
{
	var result = 0;
	var obj = this.element_first;
	
	while (obj)
	{
		result ++;
		obj = obj.element_next;
	}
	return result;
}

/* ********************************************************************************************************** */

function _joChain_AppendElement (chain_obj, append_after_obj)
{
	if (append_after_obj && append_after_obj.element_next)
	{
		append_after_obj.element_next.element_prev = chain_obj;
		chain_obj.element_next = append_after_obj.element_next;
		
		append_after_obj.element_next = chain_obj;
		chain_obj.element_prev = append_after_obj;
	}
	else
	{
		chain_obj.element_prev 	= this.element_last;
		chain_obj.element_next		= null;
	
		if (!this.element_first) 
		{
			this.element_first 		= chain_obj;
		}
		else
		{
			this.element_last.element_next 	= chain_obj;
		}
		this.element_last 			= chain_obj;
	}
	return chain_obj;
}

/* ********************************************************************************************************** */

function _joChain_SwapElements (first_element, second_element)
{
	if (first_element && second_element)
	{
		var aux_element;
		
		if (first_element.element_next == second_element)
		{
			if (first_element.element_prev) first_element.element_prev.element_next = second_element;
			if (second_element.element_next) second_element.element_next.element_prev = first_element;
			first_element.element_next = second_element.element_next;
			second_element.element_prev = first_element.element_prev;
			second_element.element_next = first_element;
			first_element.element_prev = second_element;
		}
		else if (first_element.element_prev == second_element)
		{
			if (second_element.element_prev) second_element.element_prev.element_next = first_element;
			if (first_element.element_next) first_element.element_next.element_prev = second_element;
			first_element.element_prev = second_element.element_prev;
			second_element.element_next = first_element.element_next;
			second_element.element_prev = first_element;
			first_element.element_next = second_element;
		}
		else
		{
			if (first_element.element_next) 
				first_element.element_next.element_prev = second_element;
			if (second_element.element_next) 
				second_element.element_next.element_prev = first_element;
			
			if (first_element.element_prev) 
				first_element.element_prev.element_next = second_element;
			if (second_element.element_prev) 
				second_element.element_prev.element_next = first_element;
			
			aux_element 						= first_element.element_next;
			first_element.element_next 	= second_element.element_next;
			second_element.element_next 	= aux_element;
	
			aux_element 						= first_element.element_prev;
			first_element.element_prev	= second_element.element_prev;
			second_element.element_prev	= aux_element;
		}
		
		if (!first_element.element_prev) this.element_first = first_element;
		else if (!second_element.element_prev) this.element_first = second_element;
		
		if (!first_element.element_next) this.element_last = first_element;
		else if (!second_element.element_next) this.element_last = second_element;
	}
}

/* ********************************************************************************************************** */

function _joChain_MoveElementToEnd (element)
{
	if (element && element.element_next)
	{
		if (element.element_prev)
				element.element_prev.element_next = element.element_next;
		else	this.element_first = element.element_next;
		
		element.element_next.element_prev = element.element_prev;
		
		this.element_last.element_next = element;
		element.element_prev = this.element_last;
		this.element_last = element;
		element.element_next = null;
	}
}

/* ********************************************************************************************************** */

function _joChain_MoveElementToStart (element)
{
	if (element && element.element_prev)
	{
		if (element.element_next)
				element.element_next.element_prev = element.element_prev;
		else	this.element_last = element.element_prev;
		
		element.element_prev.element_next = element.element_next;
		
		this.element_first.element_prev = element;
		element.element_next = this.element_first;
		this.element_first = element;
		element.element_prev = null;
	}
}

/* ********************************************************************************************************** */

function _joChain_RemoveAllElements()
{
	var del_entity;
	var entity	= this.element_last;
	while (entity)
	{
		del_entity = entity;
		this.RemoveElement (del_entity);
		entity = entity.element_prev;
	}
	
	this.element_first = null;
	this.element_last = null;
}

/* ********************************************************************************************************** */

function _joChain_RemoveElement (del_element)
{
	var result	= false;

	if (del_element)
	{
		if (del_element.element_prev) 	del_element.element_prev.element_next 	= del_element.element_next;
		else										this.element_first 				= del_element.element_next;
		if (del_element.element_next) 	del_element.element_next.element_prev 	= del_element.element_prev;
		else										this.element_last					= del_element.element_prev;
		
		del_element = null;
		result = true;
	}

	return result;
}

