#ifndef TRI_TCI_CALL_DATA_H
#define TRI_TCI_CALL_DATA_H

#ifndef WIN32
#include "mrevent.h"
#endif

#ifdef _WIN32
#define THREAD_ID_TYPE unsigned long
#else
#define THREAD_ID_TYPE pthread_t
#endif

typedef struct AbstractTriAckMessage
{
	unsigned long nSourceThreadId;
	int nServerId;
	int nLocalId;
	int messageCode;
	char* pData;
	int nLen;
} AbstractTriAckMessage;

typedef AbstractTriAckMessage AbstractTriTciMessage;

typedef struct TriTciCallData
{
#ifdef _WIN32
	void * evAck, * evRestart, * evDone;
#else
	int nRestart;
	struct mrevent evAck, evDone;
#endif
	AbstractTriAckMessage *msg;
	int requiredAck;
	unsigned long nWaitingTime;
	unsigned long nStartingTime;
} TriTciCallData;

typedef struct TriTciCallDataStack
{
	TriTciCallData ** pData;
	int allocated;
	int items;
}TriTciCallDataStack;

typedef struct LocalCallStack
{
	TriTciCallDataStack * stack;
	int nLocalId;
	int nRemoteId;
	THREAD_ID_TYPE nThreadId;
	int isInternal;
}LocalCallStack;

TriTciCallData* newTriTciCallData(int requiredAck, int nWaitingTime);
void disposeStack(TriTciCallDataStack * st);
void disposeCallData(TriTciCallData* data);
int acceptMsg(TriTciCallData *cd, AbstractTriAckMessage *msg);
void stop(TriTciCallData * cd);
void suspendWaiting(TriTciCallData *cd);
void restartWaiting(TriTciCallData *cd);
AbstractTriAckMessage* waitForAck(TriTciCallData *cd);
int getEllapsedTime(int nStartingTime);

TriTciCallDataStack* newTriTciCallDataStack();
void increaseStackSize(TriTciCallDataStack *stack);
void pushItem(TriTciCallDataStack *st, TriTciCallData *data);
TriTciCallData * popItem(TriTciCallDataStack *st);
TriTciCallData * peekItem(TriTciCallDataStack *st);

LocalCallStack * newLocalCallStack();
void disposeLocalCallStack(LocalCallStack * lcs);

AbstractTriAckMessage * newAstractTriTciMessage();
void disposeAbstractMsg(AbstractTriAckMessage* msg);

#endif
