/*
   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>
#ifdef __FreeBSD__
#include <sys/types.h>
#endif

//! \brief Element for the linked lists.
/**
ListElement is the structure used for linked lists in Adun. Its main use is
for holding information related to the common nonbonded interactions in molecular force fields,
i.e. lennard joned and coulomb, although it can be adapted for other uses.
The params member is used to hold the precomputed lennard jones parameters 
along with the product of the partial charges. The basic Adun force field functions for nonbonded interactions
are tailored to use this structure which can result in 
up to a 20% increase in speed compared to storing the precomputed parameters 
in another memory area e.g. in a matrix of precomputed values.
\note May create a more general list element type for use in other circumstances.
\ingroup Types
**/

typedef struct el_t 
{	
	struct el_t *next;
        int bond[2];
	double params[3];	//!< Used for holding the two LJ parameters and the product of the partial charges.
	double length;
        struct el_t *previous;
	int8_t free;
}
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
