/*
   Project: Adun

   Copyright (C) 2005 Michael Johnston & Jordi Villa-Freixa

   Author: Michael Johnston

   This application is free software; you can redistribute it and/or
   modify it under the terms of the GNU General Public
   License as published by the Free Software Foundation; either
   version 2 of the License, or (at your option) any later version.

   This application is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Library General Public License for more details.

   You should have received a copy of the GNU General Public
   License along with this library; if not, write to the Free
   Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA.
*/

#ifndef LINKED_LIST
#define LINKED_LIST

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

//! \brief Element for the linked list objects that hold the non_bonded interactions
/**
ListElement is the structure used for linked lists in Adun. Its main use is
in non bonded interactions
\todo the use of the params element needs to be deprecated. 
\ingroup Types
**/

typedef struct el_t 
{	
	struct el_t *next;
        struct el_t *previous;
        int bond[2];
	float params[2];
	double length;
}
ListElement;

/**
\defgroup Link Linked List
\ingroup Functions
@{
**/

 /**
 	Creates a new linked list whose beginning is pointed to be liststart_p.
	liststart_p must already be pointing to an allocated ListElement strcuture.
	The function returns a pointer to the last element of the list
**/
ListElement* AdLinkedListCreate(ListElement*);
 /**
 	Adds an elements to the linked list. If index is not specified element is added to the end.
	If list element passed to this function is not the last it will exit.
	\param list_el A pointer to the element to be added
	\param list_end A pointer to the end of the list
	\param index The index at which to insert the list. Currently not implemented
	\return 0 on success, -1 on failure
**/	
inline int AdSafeLinkedListAdd(ListElement*, ListElement*, int);
/**
 	Same as AdSafeLinkedListAdd but doesn't check if you've passed
	the last element.
**/ 
inline int AdUnsafeLinkedListAdd(ListElement*, ListElement*, int);
/**
	Reinserts an element extracted with AdUnsafeLinkedListExtract
	Does not check that ListElement actually points to an element
	in a real list
**/
inline int AdUnsafeLinkedListReinsert(ListElement*);
/**
 	Removes the element passed from the list. You CANNOT remove the first and last
 	element (big trouble if you do)
	\param list_el Pointer to the list element to be removed
	\returns 0 if succeds. -1 if you tried to remove the first or last list elements.
**/ 
inline int AdSafeLinkedListRemove(ListElement*);
/**
	The same as AdUnsafeLinkedListRemove except doesnt set the remove
	elements previous and next pointer to nil
	\param list_el Pointer to the list element to be removed
	\returns 0 if succeds. -1 if you tried to remove the first or last list elements.
**/ 

inline int AdUnsafeLinkedListExtract(ListElement *list_el);
/**
 	Same as safe_linked_list_remove() but doesn't check if the
	element is the first or last. Use with care.
**/ 
inline int AdUnsafeLinkedListRemove(ListElement*);
 /** Returns a pointer to the last element of the list.  **/
inline ListElement* AdLinkedListEnd(ListElement*);
 /** Returns a pointer to the first element of the list **/
inline ListElement* AdLinkedListStart(ListElement*);
inline int AdLinkedListCount(ListElement*);

/** \@}**/

#endif
