/*
Copyright (c) 2013-2014 Gustav Hartvigsson

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/

#pragma once

#include <stdlib.h>
#include <stdbool.h>
#include <assert.h>
#include "defs.h"
#include "Func.h"

/** @file
 * @defgroup SLinkedList SLinkedList
 * @{
 * A SLinkedList represents a linked list. A linked list is an efficient data
 * structure. It is not posible to index a linked list.
 */

S_BEGIN_DECLS

/**
 * Represents an object in a SLinkedList.
 */
typedef struct SLinkedListNode SLinkedListNode;

/**
 * A linked list is a data stucture that holds information in a non-idexible
 * way. It is good when the objects in the list in verry mutable, but has a
 * linear search time.
 */
typedef struct SLinkedList SLinkedList;


/**
 * Create a new linked list.
 * 
 * @param free_func the function to be used when freeing a linked list,
 * if it is NULL the free func will be set to the standard free() function.
 */
S_EXPORTED
SLinkedList *
s_linked_list_new (FreeFunc free_func);


/**
 * frees a linked list.
 * 
 * @param self the linked list to free.
 * @param free_data default:true, wether or not to free the data in the list
 *   as well as the list.
 */
S_EXPORTED
void
s_linked_list_free (SLinkedList * self, sboolean free_data);

/**
 * Add an item to a linked list (after current).
 *
 * @param self the list to add an itme to.
 * @param data the data to be stored.
 */
S_EXPORTED
void
s_linked_list_add (SLinkedList * self, spointer data);

/**
 * Add an item to the front of the list (head).
 * 
 * The new item will become the new head.
 */
S_EXPORTED
void
s_linked_list_prepend (SLinkedList * self, spointer data);

/**
 * Add on item to the end of the list (tail).
 *
 * The new item will become the new tail.
 */
S_EXPORTED
void
s_linked_list_append (SLinkedList * self, spointer data);

/**
 * Iterate to the next item. This function does not return anything.
 * 
 * @param self the list to iterate over.
 */
S_EXPORTED
sboolean
s_linked_list_next (SLinkedList * self);

/**
 * Iterate to the provious item. This function does not return anything.
 * 
 * @param self the list to iterate over.
 */
S_EXPORTED
sboolean
s_linked_list_prev (SLinkedList * self);

/**
 * Get the current item.
 */
S_EXPORTED
spointer
s_linked_list_get_current (SLinkedList * self);

/**
 * Get the next item.
 */
S_EXPORTED
spointer
s_linked_list_get_next (SLinkedList * self);

/**
 * Get previous item.
 */
S_EXPORTED
spointer
s_linked_list_get_prev (SLinkedList * self);

/**
 * Wind the list to the head (start).
 */
S_EXPORTED
void
s_linked_list_head (SLinkedList * self);

/**
 * Wind the the list to the tail (end).
 */
S_EXPORTED
void
s_linked_list_tail (SLinkedList * self);

/**
 * Get the length of the list.
 *
 * @warning the value may be wrong.
 */
S_EXPORTED
size_t
s_linked_list_len (SLinkedList * self);

/**
 * Romoves the cerrunt object useing the free function provided when
 * creating the list in s_linked_list_new ().
 */
S_EXPORTED
void
s_linked_list_remove_current (SLinkedList * self, sboolean free_data);

/**
 * Do a for each on a list.
 *
 * @param self The LinkedList to perform the for each on.
 * @param func The for each function to be used.
 * @param user_data The data to be fed to/from the function.
 * 
 * @note The function must take into accoust that the data may be NULL.
 *       The checking is not done by the function becouse the data may be a
 *       valid zero number.
 */
S_EXPORTED
void
s_linked_list_for_each (SLinkedList * self, ForEachFunc func,
                        spointer user_data);

S_END_DECLS

/** @} */
