#ifndef _MY_LINKEDLIST_H_
#define _MY_LINKEDLIST_H_

/* Holds user provided data as well as adjacent nodes */
typedef struct Node
{
	void* data; /* Generic pointer to the data */
	struct Node* next;
	struct Node* prev;
} Node;

typedef struct LinkedList
{
	Node* head;
	Node* tail;
	int size;
	/*
	 * The cleanup function is called to free the generic data
	 * the user provided, not the nodes of the list itself.
	 */
	void (*cleanup_function)(void*);
} LinkedList;

LinkedList* list_create(void (*cleanup_function)(void*));
/* int list_add_first(LinkedList* L, void* item); */
int list_add_last(LinkedList* L, void* item);
/* 
 * int list_add_at(LinkedList* L, void* item, int index);
 * int list_contains_value(LinkedList* L, void* item, int item_size);
 * int list_contains_ptr(LinkedList* L, void* item);
 * void* list_get_first(LinkedList* L);
 * void* list_get_last(LinkedList* L);
 * void* list_get_at(LinkedList* L, int index);
 * int list_remove_first(LinkedList* L);
 * int list_remove_last(LinkedList* L);
 * int list_remove_at(LinkedList* L, int index);
 * int list_clear(LinkedList* L); 
 */
int list_size(LinkedList* L);
int list_destroy(LinkedList* L);
int list_reverse(LinkedList* L);
void list_foreach(LinkedList* L, void (*function_to_apply)(void*));
void list_foreach_where(LinkedList* L, void (*function_to_apply)(void*),
	int (*condition)(void*));
int list_sort(LinkedList* L, int (*cmp)(void*, void*));

#endif