#ifndef __DATASTRUCTURE_H__
#define __DATASTRUCTURE_H__

#ifdef __cplusplus
#ifndef BEGIN_DECLS
#define BEGIN_DECLS extern "C" {
#endif
#ifndef END_DECLS
#define END_DECLS }
#endif
#else
#ifndef BEGIN_DECLS
#define BEGIN_DECLS
#endif
#ifndef END_DECLS
#define END_DECLS
#endif
#endif

BEGIN_DECLS

/*
#include <pthread.h>
#include <stdbool.h>
#include <stdint.h>
#include <limits.h>
*/
#if defined(_WIN32) && defined(UNICODE)
#include <wchar.h>
#endif

#include <limits.h>


#include "Common.h"
#include "StringUtil.h"
#include "Config.h"
#include "Log.h"

#define DS_ERR_SUCCESS          0
#define DS_ERR_EMPTY_NODE      -1

/*******************
 *
 */
struct DOUBLELINKEDLISTNODE
{
    void *pNodeData;
    struct DOUBLELINKEDLISTNODE *pPrevNode;
    struct DOUBLELINKEDLISTNODE *pNextNode;
};

struct DOUBLELINKEDLISTINFO
{
    struct DOUBLELINKEDLISTNODE *pHeadNode;
    struct DOUBLELINKEDLISTNODE *pTailNode;
    struct DOUBLELINKEDLISTNODE *pCurrentNode;
    int nNodeCount;
    pthread_mutex_t sDataMutex;
};


struct LINKEDLISTNODE
{
    void *pNodeData;
    struct LINKEDLISTNODE *pNextNode;

};

struct LINKEDLISTINFO
{
    struct LINKEDLISTNODE *pHeadNode;
    struct LINKEDLISTNODE *pCurrentNode;
    int nNodeCount;
    pthread_mutex_t sDataMutex;
};


int InitLinkedList(struct LINKEDLISTINFO *pListInfo);

int LinkedListAddNodeToHead(struct LINKEDLISTINFO *pListInfo, void *pData, struct LINKEDLISTNODE **ppNode);

int LinkedListMoveToHead(struct LINKEDLISTINFO *pListInfo, struct LINKEDLISTNODE **ppNode);

int LinkedListMoveToNext(struct LINKEDLISTINFO *pListInfo, struct LINKEDLISTNODE **ppNode);

int LinkedListGetCurrentNode(struct LINKEDLISTINFO *pListInfo, struct LINKEDLISTNODE **ppNode);

int LinkedListRemoveHeadNode(struct LINKEDLISTINFO *pListInfo, struct LINKEDLISTNODE **ppNode);

int LinkedListNodeExist(struct LINKEDLISTINFO *pListInfo, int *bNodeExist);

int InitDoubleLinkedList(struct DOUBLELINKEDLISTINFO *pListInfo);

int DoubleLinkedListAddNodeToHead(struct DOUBLELINKEDLISTINFO *pListInfo, void *pData, struct DOUBLELINKEDLISTNODE **ppNode);

int DoubleLinkedListAddNodeToTail(struct DOUBLELINKEDLISTINFO *pListInfo, void *pData, struct DOUBLELINKEDLISTNODE **ppNode);

int DoubleLinkedListMoveToHead(struct DOUBLELINKEDLISTINFO *pListInfo, struct DOUBLELINKEDLISTNODE **ppNode);

int DoubleLinkedListMoveToTail(struct DOUBLELINKEDLISTINFO *pListInfo, struct DOUBLELINKEDLISTNODE **ppNode);

int DoubleLinkedListMoveToNext(struct DOUBLELINKEDLISTINFO *pListInfo, struct DOUBLELINKEDLISTNODE **ppNode);

int DoubleLinkedListMoveToPrev(struct DOUBLELINKEDLISTINFO *pListInfo, struct DOUBLELINKEDLISTNODE **ppNode);

int DoubleLinkedListGetCurrentNode(struct DOUBLELINKEDLISTINFO *pListInfo, struct DOUBLELINKEDLISTNODE **ppNode);

int DoubleLinkedListRemoveHeadNode(struct DOUBLELINKEDLISTINFO *pListInfo, struct DOUBLELINKEDLISTNODE **ppNode);

int DoubleLinkedListRemoveTailNode(struct DOUBLELINKEDLISTINFO *pListInfo, struct DOUBLELINKEDLISTNODE **ppNode);

// 노드 유무를 확인하여 리턴한다. Head가 노드를 가지는 경우 true, 없는 경우 false가 된다.
int DoubleLinkedListNodeExist(struct DOUBLELINKEDLISTINFO *pListInfo, int *bNodeExist);

// 현재 노드를 반환하며 리스트에서 현재 노드를 삭제 하고 현재 노드는 다음 노드가 된다.
int DoubleLinkedListRemoveCurrentNode(struct DOUBLELINKEDLISTINFO *pListInfo, struct DOUBLELINKEDLISTNODE **ppNode);

END_DECLS

#endif
