#ifndef __OrderedSet__H
#define __OrderedSet__H

#include "WimpLib:std.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct OrderedSet OrderedSet;
typedef struct OrderedSetVPtr OrderedSetVPtr;
typedef struct OrderedNode OrderedNode;

typedef void* (*OrderedSet_FAlloc)(void* pHandle, const void* pData) throws(mem);
typedef void (*OrderedSet_FDelete)(void* pHandle, void* pData);
typedef int (*OrderedSet_FCompare)(const void*, const void*);

/*
 * FAlloc    Function used to make a copy of any data to insert.
 *           Use NULL to simply insert the original data.
 * FDelete   Function used to delete the data associated to any deleted node.
 *           Use NULL if alloc is NULL.
 * FCompare  Function to use to compare elements for ordering.
 */

struct OrderedSetVPtr
{
	OrderedSet_FAlloc    FAlloc;
	OrderedSet_FDelete   FDelete;
	OrderedSet_FCompare  FCompare;
};

OrderedSet*  New_OrderedSet            (void* pHandle, const OrderedSetVPtr* VPtr) throws(mem);
void         Delete_OrderedSet         (OrderedSet*);

int          OrderedSet_Count          (const OrderedSet*);
OrderedSet_FCompare OrderedSet_GetFCompare(const OrderedSet*);

OrderedNode* OrderedSet_Add            (OrderedSet*, const void* pData) throws(mem);
OrderedNode* OrderedSet_Update         (OrderedSet*, OrderedNode* pNode) throws(null);
void         OrderedSet_AddNode        (OrderedSet* This, OrderedNode* pNode);

void         OrderedSet_RemoveNode     (OrderedSet*, OrderedNode* pNode);
void         OrderedSet_Remove         (OrderedSet*, int index) throws(index);
void         OrderedSet_Clear          (OrderedSet*);

int          OrderedSet_GetNodeIndex   (const OrderedSet*, const OrderedNode* pNode) throws(null);
const void*  OrderedSet_GetNodeData    (const OrderedSet*, const OrderedNode* pNode) throws(null);
OrderedNode* OrderedSet_GetSuccessor   (const OrderedSet*, const OrderedNode* pNode);
OrderedNode* OrderedSet_GetPredeccessor(const OrderedSet*, const OrderedNode* pNode);
OrderedNode* OrderedSet_FindNode       (const OrderedSet*, const void* pData);

const void*  OrderedSet_Get            (const OrderedSet*, int index) throws(index);
OrderedNode* OrderedSet_GetNode        (const OrderedSet*, int index) throws(index);
int          OrderedSet_Find           (const OrderedSet*, const void* pData) throws(index);

OrderedNode* OrderedSet_LowerBound     (const OrderedSet*, OrderedSet_FCompare, const void* pData);
OrderedNode* OrderedSet_UpperBound     (const OrderedSet*, OrderedSet_FCompare, const void* pData);

#ifdef __cplusplus
}
#endif

#endif
