/*
*                    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.
*/


#ifndef NDEF_MESSAGE_H_
#define NDEF_MESSAGE_H_

#ifdef __cplusplus
extern "C" {
#endif  /* __cplusplus */

/* ********************************************************************************************
* Includes
* ******************************************************************************************* */
#include <stdint.h>
#include "NDEF_Config.h"
#include "NDEF_Status.h"
#include "NDEF_Record.h"
#include "Records/NDEF_Rec_Handover.h"

/** \defgroup Msg  Message Interface
*
* \brief
* @{
*/

/* ********************************************************************************************
* MACROS/Defines
* ******************************************************************************************* */



/* ********************************************************************************************
* Types/Structure Declarations
* ******************************************************************************************* */

/**
* \brief Record node
*/
typedef struct RecNode
{
	struct RecNode * pPrevNode;		/**< Pointer to previous node in linked list. */
	struct RecNode * pNextNode;		/**< Pointer to node node in linked list. */
	void * pRecord;					/**< Record handle. */
}RecNode_t;



/**
* \brief Ndef Message structure
*/
typedef struct
{
	uint16_t	wRecordsInMessage;	/**< Number of records in message */
	RecNode_t * pFirstNode;			/**< Pointer to first node of linked list. */
	RecNode_t * pLastNode;			/**< Pointer to last node of linked list. */
}NDEF_Message_t;


/* ********************************************************************************************
* Function Prototypes
* ******************************************************************************************* */

/**
 * \brief This function will append the record specified by record handle into message specified by message handle.
 *
 *		  When appending initial record into the message (message is unitialized), message handle needs to be set to NULL. In this case  NDEF_Message_t structure is  allocated on heap and the reference is saved to message handle.
 *		  Internally the message works as double linked list of records, where both first record and last record references are stored  in message along with number of records inside the message. Therfore appending a record will
 *		  allocate the record node on heap and set the reference in message handle. 
 *
 * @param[in] 	 ppMessage		Pointer to message handle.
 * @param[in]	 pRecord		Record handle.
 *
 * @return Status of the API
 * @retval NDEF_STATUS_SUCCESS				Function returned successfully.
 * @retval NDEF_STATUS_ERROR_INVALID_PARAM	Null/Invalid function parameter.
 * @retval NDEF_STATUS_ERROR_NULL_PTR		Failed malloc.
 */
extern Status_t NDEF_Msg_AppendRecord(NDEF_Message_t ** ppMessage,const  void * pRecord);

/**
 * \brief This function is identical to NDEF_Msg_AppendRecord with the difference of prepending the record instead of appending  - reference to record will be added to start of the linked list (index 0).
 *
 * @param[in] 	 ppMessage		Pointer to message handle.
 * @param[in]	 pRecord		Record handle.
 *
 * @return Status of the API
 * @retval NDEF_STATUS_SUCCESS				Function returned successfully.
 * @retval NDEF_STATUS_ERROR_INVALID_PARAM	Null/Invalid function parameter.
 * @retval NDEF_STATUS_ERROR_NULL_PTR		Failed malloc.
 */
extern Status_t NDEF_Msg_PrependRecord(NDEF_Message_t ** ppMessage, const void * pRecord);



/**
 * \brief This function is used to return internal type identifictaion number of a record at specified index from a message specified by handle. Note: Message indexing starts at 0.
 *
 * @param[in] 		pMessage	   		Message handle.
 * @param[in]		wIndex				Index of a record.
 *
 * @return TypeId of the record.
 * @retval In case of error returns NULL.
 */
extern RecordTypeId_t NDEF_Msg_GetRecTypeByIndex(NDEF_Message_t * pMessage, uint16_t wIndex);

/**
 * \brief This function is used to return handle  of a record at specified index from a message specified by handle. Note: Message indexing starts at 0.
 *
 * @param[in] 		pMessage	   	Message handle.
 * @param[in]		wIndex			Index of a record.
 *
 * @return Record handle
 * @retval In case of error returns NULL.
 */
extern void * NDEF_Msg_GetRecHandleByIndex(const NDEF_Message_t * pMessage, uint16_t wIndex);

/**
 * \brief This function is used to return number of records assigned to a message specified by handle. 
 *
 * @param[in] 		pMessage	   	Message handle.
 *
 * @return Number of records 
 * @retval In case of error returns 0.
 */
extern uint16_t NDEF_Msg_GetNumberOfRecords(const NDEF_Message_t *  pMessage);


/**
 * \brief TODO This function is used decode Ndef message in form of byte array and parse parameters into structures. Decoded Ndef message, including all records and their payload will be stored on heap.
 *
 * @param[in]		pByteArray		Input buffer.
 * @param[in]		wLength			Length of byte array  - used for boundary check.
 *
 * @return Message handle
 * @retval In case of error returns NULL.
 */
extern NDEF_Message_t * NDEF_Msg_DecodeFromByteArray(const uint8_t * pByteArray, uint32_t  dwLength);


/**
 * \brief TODO This function is used to serialize a message specified by handle into a output buffer. Before the serialization of a message is done, this function will also fill header parameters for all records associated with message.
 *
 * @param[in] 			pMessage	   	Message handle.
 * @param[in]	  		wLength	 		Size of output buffer - used for boundary check.
 * @param[out]			pByteArray		Output buffer.
 *
 * @return Number of bytes written into output buffer
 * @retval In case of error returns 0.
 */
extern uint32_t NDEF_Msg_EncodeToByteArray(NDEF_Message_t  * pMessage, uint8_t * pByteArray, uint32_t  dwLength);


/**
 * \brief This function is used remove reference to a  record at specific index from  a message specified by handle.  Additionaly all  resources  used by this record will be freed. 
 *        Notes: References to this record on application layer will no longer be valid. Message indexing starts at 0. 
 *
 * @param[in] 		pMessage	   	Message handle.
 * @param[in]		wIndex			Index of a record to be removed.
 *
 * @return Status of the API
 * @retval NDEF_STATUS_SUCCESS				Function returned successfully.
 * @retval NDEF_STATUS_ERROR_INVALID_PARAM	Null/Invalid function parameter.
 */
extern Status_t NDEF_Msg_DestroyRecByIndex(NDEF_Message_t  * pMessage, uint16_t wIndex);


/**
* \brief This function is used  to remove reference to a  record specified by handle from  a message specified by handle.  Additionaly all  resources  used by this record will be freed.
*		 Notes: References to this record on application layer will no longer be valid.
* @param[in] 		pMessage	   	Message handle.
* @param[in]		wIndex			Index of a record to be removed.	
*
* @return Status of the API
* @retval NDEF_STATUS_SUCCESS				Function returned successfully.
* @retval NDEF_STATUS_ERROR_INVALID_PARAM	Null/Invalid function parameter.
*/
extern Status_t NDEF_Msg_DestroyRecByHandle(NDEF_Message_t  * pMessage, void * pHandle);

/**
 * \brief    This function is used to free all resources used by message specified by handle along with assigned records. Message handle will be set to NULL.
 *		     Note: References to these records on application layer will no longer be valid.
 *
 * @param[in] 		pMessage	   		Message handle.
 *
 * @return Status of the API
 * @retval NDEF_STATUS_SUCCESS				Function returned successfully.
 * @retval NDEF_STATUS_ERROR_INVALID_PARAM	Null/Invalid function parameter.
 */
extern Status_t NDEF_Msg_DestroyMsg(NDEF_Message_t  ** ppMessage);


/**
 * \brief PHASE2 - This high level API function is used to create a HandoverSelect message with just one alternative carrier  and no auxiliary data. Message created by this function will contain 3 records - HandoverSelect, AlternativeCarrier, CarrierData where only CarrierData are needed as input from application.
 *
 * @param[in]		pCarrierRecord			Pointer to carrier record - handle of record containing carrier data (for example Btssp).
 *
 * @return Message handle
 * @retval NULL in case of an error
 */
extern NDEF_Message_t * NDEF_Msg_CreateSimpleHandover(void * pCarrierRecord);

#ifdef NDEF_BUILD_JSON_IMPORT_EXPORT

/**
 * \brief PHASE2 This function is used to export a message specified by handle into an output buffer in JSON format.
 *
 * @param[in] 	  pMessage   Message handle.
 * @param[out] 	  pOutput 	 Pointer to output buffer.
 * @param[in]	  dwLength	 Size of output buffer.
 *
 * @return Number of bytes written into output buffer
 */
extern uint16_t NDEF_Msg_ExportToJson(const NDEF_Message_t  * pMessage, uint8_t * pOutput, uint32_t dwLength);


/**
 * \brief PHASE2 This function is used to import a message in JSON format from application buffer to a NDEF_Message_t structure. All structures created by this function are stored on heap.
 *
 * @param[in] 	  pInput 	Pointer to output buffer.
 * @param[in] 	  dwLength	Length of the JSON formatted text.
 *
 * @return Message handle
 * @retval In case of error returns NULL.
 */
extern NDEF_Message_t * NDEF_Msg_ImportFromJson(uint8_t * pInput, uint32_t dwLength);
#endif

/** @}
* end of  Msg Ndef Message Interface
*/


#ifdef __cplusplus
} /* Extern C */
#endif

#endif /* NDEF_MESSAGE_H_ */
