#include "Shared/CommonTri.h"
#include <malloc.h>
#include <string.h>

#ifdef _WIN32
	#ifdef _MSC_VER
		#if _MSC_VER >= 1600
			#include <stdint.h>
		#else
			typedef short int16_t;
			typedef int int32_t;
			typedef __int64 int64_t;
		#endif
	#else
		#include <stdint.h>
	#endif
#else
#include <stdint.h>
#endif

// SA callbacks
FTriSAReset pTriSAResetCallback = NULL;
FTriExecuteTestCase pTriExecuteTestCaseCallback = NULL;
FTriMap pTriMapCallback = NULL;
FTriUnmap pTriUnmapCallback = NULL;
FTriEndTestCase pTriEndTestCaseCallback = NULL;
FTriSend pTriSendCallback = NULL;
FTriSendBC pTriSendBCCallback = NULL;
FTriSendMC pTriSendMCCallback = NULL;
FTriCall pTriCallCallback = NULL;
FTriCallBC pTriCallBCCallback = NULL;
FTriCallMC pTriCallMCCallback = NULL;
FTriReply pTriReplyCallback = NULL;
FTriReplyBC pTriReplyBCCallback = NULL;
FTriReplyMC pTriReplyMCCallback = NULL;
FTriRaise pTriRaiseCallback = NULL;
FTriRaiseBC pTriRaiseBCCallback = NULL;
FTriRaiseMC pTriRaiseMCCallback = NULL;
FTriSUTActionInformal pTriSUTActionInformalCallback = NULL;

// PA callbacks
FTriPAReset pTriPAResetCallback = NULL;
FTriStartTimer pTriStartTimerCallback = NULL;
FTriStopTimer pTriStopTimerCallback = NULL;
FTriReadTimer pTriReadTimerCallback = NULL;
FTriTimerRunning pTriTimerRunningCallback = NULL;
FTriExternalFunction pTriExternalFunctionCallback = NULL;

// Service callbacks
FOnError pOnErrorCallback = NULL;
FOnConnectionEstablished pOnConnectionEstablishedCallback = NULL;
FOnConnectionClosed pOnConnectionClosedCallback = NULL;


void copyBinaryString(BinaryString * pTargetString, const BinaryString * pSrcString)
{
	if (pSrcString->bits > 0)
	{
		int nLen = pSrcString->bits / 8;
		if (pSrcString->bits % 8 > 0)
			nLen++;
		pTargetString->data = (unsigned char *)malloc(nLen);
		memcpy(pTargetString->data, pSrcString->data, nLen);
	}
	else
		pTargetString->data = NULL;
	pTargetString->bits = pSrcString->bits;
	pTargetString->aux = pSrcString->aux;
}

char * copyString(const char * pszSrc)
{
	char * pszRes = NULL;
	if (pszSrc)
	{
		size_t nLen = strlen(pszSrc) + 1;
		pszRes = (char*)malloc(nLen);
		memcpy(pszRes, pszSrc, nLen);
	}
	return pszRes;
}

void copyQualifiedName(QualifiedName * pTargetName, const QualifiedName * pSrcName)
{
	pTargetName->moduleName = copyString(pSrcName->moduleName);
	pTargetName->objectName = copyString(pSrcName->objectName);
	pTargetName->aux = pSrcName->aux;
}

void copyTriAddress(TriAddress * pTargetAddress, const TriAddress * pSrcAddress)
{
	copyBinaryString(pTargetAddress, pSrcAddress);
}

void copyTriAddressList(TriAddressList * pTargetAddressList, const TriAddressList * pSrcAddressList)
{
	int i;
	pTargetAddressList->length = pSrcAddressList->length;
	pTargetAddressList->addrList = (TriAddress**)malloc(pSrcAddressList->length * sizeof(TriAddress*));
	for (i = 0; i < pSrcAddressList->length; i++)
	{
		pTargetAddressList->addrList[i] = (TriAddress*)malloc(sizeof(TriAddress));
		copyTriAddress(pTargetAddressList->addrList[i], pSrcAddressList->addrList[i]);
	}
}

void copyTriComponentId(TriComponentId * pTargetComponentId, const TriComponentId * pSrcComponentId)
{
	copyBinaryString(&pTargetComponentId->compInst, &pSrcComponentId->compInst);
	pTargetComponentId->compName = copyString(pSrcComponentId->compName);
	copyQualifiedName(&pTargetComponentId->compType, &pSrcComponentId->compType);
}

void copyTriComponentIdList(TriComponentIdList * pTargetList, const TriComponentIdList * pSrcList)
{
	int i;
	pTargetList->length = pSrcList->length;
	pTargetList->compIdList = (TriComponentId**)malloc(pSrcList->length * sizeof(TriComponentId*));
	for (i = 0; i < pSrcList->length; i++)
	{
		pTargetList->compIdList[i] = (TriComponentId*)malloc(sizeof(TriComponentId));
		copyTriComponentId(pTargetList->compIdList[i], pSrcList->compIdList[i]);
	}
}

void copyTriException(TriException * pTargetException, const TriException * pSrcException)
{
	copyBinaryString(pTargetException, pSrcException);
}

void copyTriFunctionId(TriFunctionId * pTargetFunctionId, const TriFunctionId * pSrcFunctionId)
{
	copyQualifiedName(pTargetFunctionId, pSrcFunctionId);
}

void copyTriMessage(TriMessage * pTargetMessage, const TriMessage * pSrcMessage)
{
	copyBinaryString(pTargetMessage, pSrcMessage);
}

void copyTriParameter(TriParameter * pTargetParameter, const TriParameter * pSrcParameter)
{
	copyBinaryString(&pTargetParameter->par, &pSrcParameter->par);
	pTargetParameter->mode = pSrcParameter->mode;
}

void copyTriParameterList(TriParameterList * pTargetList, const TriParameterList * pSrcList)
{
	int i;
	pTargetList->length = pSrcList->length;
	pTargetList->parList = (TriParameter**)malloc(pSrcList->length * sizeof(TriParameter*));
	for (i = 0; i < pSrcList->length; i++)
	{
		pTargetList->parList[i] = (TriParameter*)malloc(sizeof(TriParameter));
		copyTriParameter(pTargetList->parList[i], pSrcList->parList[i]);
	}
}

void copyTriPortId(TriPortId * pTargetPortId, const TriPortId * pSrcPortId)
{
	copyTriComponentId(&pTargetPortId->compInst, &pSrcPortId->compInst);
	pTargetPortId->portName = copyString(pSrcPortId->portName);
	copyQualifiedName(&pTargetPortId->portType, &pSrcPortId->portType);
	pTargetPortId->portIndex = pSrcPortId->portIndex;
	pTargetPortId->aux = pSrcPortId->aux;
}

void copyTriPortIdList(TriPortIdList * pTargetList, const TriPortIdList * pSrcList)
{
	int i;
	pTargetList->length = pSrcList->length;
	pTargetList->portIdList = (TriPortId**)malloc(pSrcList->length * sizeof(TriPortId*));
	for (i = 0; i < pSrcList->length; i++)
	{
		pTargetList->portIdList[i] = (TriPortId*)malloc(sizeof(TriPortId));
		copyTriPortId(pTargetList->portIdList[i], pSrcList->portIdList[i]);
	}
}

void copyTriSignatureId(TriSignatureId * pTargetSignatureId, const TriSignatureId * pSrcSignatureId)
{
	copyQualifiedName(pTargetSignatureId, pSrcSignatureId);
}

void copyTriTestCaseId(TriTestCaseId * pTargetTestCaseId, const TriTestCaseId * pSrcTestCaseId)
{
	copyQualifiedName(pTargetTestCaseId, pSrcTestCaseId);
}

void copyTriTimerId(TriTimerId * pTargetTimerId, const TriTimerId * pSrcTimerId)
{
	copyBinaryString(pTargetTimerId, pSrcTimerId);
}

void clearBinaryString(BinaryString * pBin)
{
	free(pBin->data);
	if(pBin->aux)
	{//so wish for a try/catch right now...
		int nStructVersion = 0;
		memcpy(&nStructVersion, pBin->aux, sizeof(int32_t));
		if(nStructVersion == 1)
			free(pBin->aux);
	}
	memset(pBin, 0, sizeof(BinaryString));
}

void clearQualifiedName(QualifiedName * pName)
{
	free(pName->moduleName);
	free(pName->objectName);
	memset(pName, 0, sizeof(QualifiedName));
}

void clearTriAddress(TriAddress * pAddress)
{
	clearBinaryString(pAddress);
}

void clearTriAddressList(TriAddressList * pList)
{
	int i;
	for (i = 0; i < pList->length; i++)
	{
		clearTriAddress(pList->addrList[i]);
		free(pList->addrList[i]);
	}
	free(pList->addrList);
	memset(pList, 0, sizeof(TriAddressList));
}

void clearTriComponentId(TriComponentId * pComp)
{
	clearBinaryString(&pComp->compInst);
	free(pComp->compName);
	clearQualifiedName(&pComp->compType);
	memset(pComp, 0, sizeof(TriComponentId));
}

void clearTriComponentIdList(TriComponentIdList * pList)
{
	int i;
	for (i = 0; i < pList->length; i++)
	{
		clearTriComponentId(pList->compIdList[i]);
		free(pList->compIdList[i]);
	}
	free(pList->compIdList);
	memset(pList, 0, sizeof(TriComponentIdList));
}

void clearTriException(TriException * pException)
{
	clearBinaryString(pException);
}

void clearTriFunctionId(TriFunctionId * pFunctionId)
{
	clearQualifiedName(pFunctionId);
}

void clearTriMessage(TriMessage * pMessage)
{
	clearBinaryString(pMessage);
}

void clearTriParameter(TriParameter * pParam)
{
	clearBinaryString(&pParam->par);
	memset(pParam, 0, sizeof(TriParameter));
}

void clearTriParameterList(TriParameterList * pList)
{
	int i;
	for (i = 0; i < pList->length; i++)
	{
		clearTriParameter(pList->parList[i]);
		free(pList->parList[i]);
	}
	free(pList->parList);
	memset(pList, 0, sizeof(TriParameterList));
}

void clearTriPortId(TriPortId * pPort)
{
	free(pPort->portName);
	clearTriComponentId(&pPort->compInst);
	clearQualifiedName(&pPort->portType);
	memset(pPort, 0, sizeof(TriPortId));
}

void clearTriPortIdList(TriPortIdList * pList)
{
	int i;
	for (i = 0; i < pList->length; i++)
	{
		TriPortId * pCurrentId = pList->portIdList[i];
		clearTriPortId(pList->portIdList[i]);
		free(pCurrentId);
	}
	free(pList->portIdList);
	memset(pList, 0, sizeof(TriPortIdList));
}

void clearTriSignatureId(TriSignatureId * pSignatureId)
{
	clearQualifiedName(pSignatureId);
}

void clearTriTestCaseId(TriTestCaseId * pTestCaseId)
{
	clearQualifiedName(pTestCaseId);
}

void clearTriTimerId(TriTimerId * pTimerId)
{
	clearBinaryString(pTimerId);
}


void setTriSAResetCallback (FTriSAReset pCallback)
{
	pTriSAResetCallback = pCallback;
}
void setTriExecuteTestCaseCallback (FTriExecuteTestCase pCallback)
{
	pTriExecuteTestCaseCallback = pCallback;
}
void setTriMapCallback (FTriMap pCallback)
{
	pTriMapCallback = pCallback;
}
void setTriUnmapCallback (FTriUnmap pCallback)
{
	pTriUnmapCallback = pCallback;
}
void setTriEndTestCaseCallback (FTriEndTestCase pCallback)
{
	pTriEndTestCaseCallback = pCallback;
}
void setTriSendCallback (FTriSend pCallback)
{
	pTriSendCallback = pCallback;
}
void setTriSendBCCallback (FTriSendBC pCallback)
{
	pTriSendBCCallback = pCallback;
}
void setTriSendMCCallback (FTriSendMC pCallback)
{
	pTriSendMCCallback = pCallback;
}
void setTriCallCallback (FTriCall pCallback)
{
	pTriCallCallback = pCallback;
}
void setTriCallBCCallback (FTriCallBC pCallback)
{
	pTriCallBCCallback = pCallback;
}
void setTriCallMCCallback (FTriCallMC pCallback)
{
	pTriCallMCCallback = pCallback;
}
void setTriReplyCallback (FTriReply pCallback)
{
	pTriReplyCallback = pCallback;
}
void setTriReplyBCCallback (FTriReplyBC pCallback)
{
	pTriReplyBCCallback = pCallback;
}
void setTriReplyMCCallback (FTriReplyMC pCallback)
{
	pTriReplyMCCallback = pCallback;
}
void setTriRaiseCallback (FTriRaise pCallback)
{
	pTriRaiseCallback = pCallback;
}
void setTriRaiseBCCallback (FTriRaiseBC pCallback)
{
	pTriRaiseBCCallback = pCallback;
}
void setTriRaiseMCCallback (FTriRaiseMC pCallback)
{
	pTriRaiseMCCallback = pCallback;
}
void setTriSUTActionInformalCallback (FTriSUTActionInformal pCallback)
{
	pTriSUTActionInformalCallback = pCallback;
}

void setTriPAResetCallback (FTriPAReset pCallback)
{
	pTriPAResetCallback = pCallback;
}
void setTriStartTimerCallback (FTriStartTimer pCallback)
{
	pTriStartTimerCallback = pCallback;
}
void setTriStopTimerCallback (FTriStopTimer pCallback)
{
	pTriStopTimerCallback = pCallback;
}
void setTriReadTimerCallback (FTriReadTimer pCallback)
{
	pTriReadTimerCallback = pCallback;
}
void setTriTimerRunningCallback (FTriTimerRunning pCallback)
{
	pTriTimerRunningCallback = pCallback;
}
void setTriExternalFunctionCallback (FTriExternalFunction pCallback)
{
	pTriExternalFunctionCallback = pCallback;
}

void setOnErrorCallback (FOnError pCallback)
{
	pOnErrorCallback = pCallback;
}
void setOnConnectionEstablishedCallback (FOnConnectionEstablished pCallback)
{
	pOnConnectionEstablishedCallback = pCallback;
}
void setOnConnectionClosedCallback (FOnConnectionClosed pCallback)
{
	pOnConnectionClosedCallback = pCallback;
}
