/*
*                    Copyright (c), NXP Semiconductors
*
*                       (C) NXP Semiconductors 2018
*
*         All rights are reserved. Reproduction in whole or in part is
*        prohibited without the written consent of the copyright owner.
*    NXP reserves the right to make changes without notice at any time.
*   NXP makes no warranty, expressed, implied or statutory, including but
*   not limited to any implied warranty of merchantability or fitness for any
*  particular purpose, or that the use will not infringe any third party patent,
*   copyright or trademark. NXP must not be liable for any loss or damage
*                            arising from its use.
*/

/* ********************************************************************************************
* Includes
* ****************************************************************************************** */
#include <stdio.h>
#include <string.h>
#include "Records/NDEF_Rec_GenericPayload.h"
#include "Internal/NDEF_RecordInternals.h"
#include "Internal/NDEF_Heap.h"

/* ********************************************************************************************
*  Definitions
* ******************************************************************************************* */


/* ********************************************************************************************
* Global and Static Variables
* Total Size: NNNbytes
* ******************************************************************************************* */

/* ********************************************************************************************
* Private Functions Prototypes
* ******************************************************************************************* */


/* ********************************************************************************************
* Public Functions
* ******************************************************************************************* */

NDEF_Rec_GenericPayload_t *  NDEF_Rec_Generic_Create(const uint8_t * pPayload, uint32_t dwLength)
{
	NDEF_Rec_GenericPayload_t * pRecord;
	uint8_t  bErrorFlag = 0;
	RETURN_NULL_ON_NULL(pPayload);
	do
	{
		pRecord = INT_MALLOC(sizeof(NDEF_Rec_GenericPayload_t));
		BREAK_ON_NULL(pRecord, bErrorFlag);
		memset(pRecord, 0, sizeof(NDEF_Rec_GenericPayload_t));

		pRecord->INT_sRecordInfo.eId = Type_Generic;

		pRecord->pPayload = INT_MALLOC(dwLength);
		BREAK_ON_NULL(pRecord->pPayload, bErrorFlag);
		memcpy(pRecord->pPayload, pPayload, dwLength);
		pRecord->INT_sRecordInfo.dwHeapUsedByPayload = dwLength;
		pRecord->sHeader.dwPayloadLength = dwLength;

	} while (0);
	if (bErrorFlag)
	{
		NDEF_Rec_Destroy((void **)(&pRecord));
	}
	return pRecord;
}



NDEF_Rec_GenericPayload_t * NDEF_Rec_Generic_CreateByPtr(const uint8_t * pPayload, uint32_t  dwLength)
{
	NDEF_Rec_GenericPayload_t * pRecord;
	uint8_t  bErrorFlag = 0;
	RETURN_NULL_ON_NULL(pPayload);
	do
	{
		pRecord = INT_MALLOC(sizeof(NDEF_Rec_GenericPayload_t));
		BREAK_ON_NULL(pRecord, bErrorFlag);
		memset(pRecord, 0, sizeof(NDEF_Rec_GenericPayload_t));

		pRecord->INT_sRecordInfo.eId = Type_Generic;

		pRecord->pPayload = (uint8_t *)pPayload;
		pRecord->sHeader.dwPayloadLength = dwLength;

	} while (0);
	if (bErrorFlag)
	{
		NDEF_Rec_Destroy((void **)(&pRecord));
		pRecord = NULL;
	}
	return pRecord;
}






Status_t NDEF_Rec_Generic_GetPayload(const NDEF_Rec_GenericPayload_t * pRecord, uint8_t * pPayload, uint32_t  dwLength)
{
	RETURN_ON_NULL_PARAM(pRecord);
	RETURN_ON_NULL_PARAM(pPayload);
	RETURN_ON_NULL_MEMBER(pRecord->pPayload);
	if (pRecord->sHeader.dwPayloadLength > dwLength)
	{
		return NDEF_STATUS_ERROR_BUFF_OVF;
	}
	memcpy(pPayload, pRecord->pPayload, dwLength);
	return NDEF_STATUS_SUCCESS;
}


uint8_t * NDEF_Rec_Generic_GetPtrToPayload(const NDEF_Rec_GenericPayload_t * pRecord)
{
	RETURN_NULL_ON_NULL(pRecord);
	return pRecord->pPayload;
}

uint32_t  NDEF_Rec_Generic_GetPayloadLen(const NDEF_Rec_GenericPayload_t * pRecord)
{
	return NDEF_Rec_GetPayloadLen(pRecord);
}

/* ********************************************************************************************
* Private Functions
* ******************************************************************************************* */


/* ********************************************************************************************
* Internal functions - not part of API
* ******************************************************************************************* */
Status_t INT_Generic_Free(void *pRecord)
{
	NDEF_Rec_GenericPayload_t * pRec;
	pRec = (NDEF_Rec_GenericPayload_t *)pRecord;
	if (pRec->INT_sRecordInfo.dwHeapUsedByPayload != 0)
	{
		INT_FREE(pRec->pPayload);
		pRec->INT_sRecordInfo.dwHeapUsedByPayload = 0;
		pRec->pPayload = NULL;
	}
	return NDEF_STATUS_SUCCESS;
}

Status_t INT_GenPayload_Serialize(void *pRecord, uint8_t * pOutput, uint32_t * pOffset)
{
	Status_t status;
	uint32_t dwPayloadLen;
	uint32_t dwOffset;
	NDEF_Rec_GenericPayload_t * pRec;

	pRec = (NDEF_Rec_GenericPayload_t *)pRecord;
	dwOffset = *pOffset;

	status = INT_Header_Serialize(pRecord, pOutput, &dwOffset);

	dwPayloadLen = NDEF_Rec_GetPayloadLen(pRec);
	memcpy(&pOutput[dwOffset], pRec->pPayload, dwPayloadLen);
	dwOffset += dwPayloadLen;

	*pOffset = dwOffset;
	return status;
}

void * INT_GenPayload_Parse(INT_FetchedHeader_t * pFetchedHeader, const uint8_t * pInput)
{

	NDEF_Rec_GenericPayload_t * pRecord;
	uint8_t bErrorFlag = 0;
	pRecord = INT_MALLOC(sizeof(NDEF_Rec_GenericPayload_t));
	RETURN_NULL_ON_NULL(pRecord);
	memset(pRecord, 0, sizeof(NDEF_Rec_GenericPayload_t));
	pRecord->INT_sRecordInfo.eId = Type_Generic;
	memcpy(&pRecord->sHeader, &pFetchedHeader->sHeader, sizeof(NDEF_Record_Header_t));
	if (pFetchedHeader->sHeader.dwPayloadLength)
	{

		do
		{
			pRecord->pPayload = INT_MALLOC(sizeof(uint8_t)*pFetchedHeader->sHeader.dwPayloadLength);
			BREAK_ON_NULL(pRecord->pPayload, bErrorFlag);
			memcpy(pRecord->pPayload, &pInput[pFetchedHeader->dwOffsetToPayload], pFetchedHeader->sHeader.dwPayloadLength);
			pRecord->INT_sRecordInfo.dwHeapUsedByPayload = pFetchedHeader->sHeader.dwPayloadLength;
		} while (0);
	}
	if (bErrorFlag)
	{
		INT_FREE(pRecord->pPayload);
		INT_FREE(pRecord);
		pRecord = NULL;
	}
	return pRecord;
}