#include "VOS_API/DX_VOS_Notification.h"
#include "VOS_API/DX_VOS_Socket.h"
#define DX_MIN_USABLE_PORT	1024
DxStatus DX_VOS_CreateSenderNotificator(DxVosSenderNotificator* notificator)
{
	DxVosSocket socket = DX_NULL;
	DX_DECLARE(DxStatus, result, DX_SUCCESS);

    DX_ASSERT_PARAM(notificator != DX_NULL);

	*notificator = DX_NULL;
	result = DX_VOS_SocketCreate(&socket, DX_AF_INET, DX_SOCK_DATAGRAM, DX_IPPROTO_UDP);

	*notificator = (DxVosSenderNotificator)socket;
    if (result != DX_SUCCESS)
    	RETURN_OLD_ERROR(result);
    DX_RETURN(DX_SUCCESS);
}

DxStatus DX_VOS_DeleteSenderNotificator(DxVosSenderNotificator notificator)
{
    DX_DECLARE(DxStatus, result, DX_SUCCESS);

    result = DX_VOS_SocketClose((DxVosSocket*)&notificator);
    if (result != DX_SUCCESS)
    	RETURN_OLD_ERROR(result);
    
    DX_RETURN(DX_SUCCESS);
}

DxStatus DX_VOS_SendNotification(DxVosSenderNotificator notificator, DxUint32 destNotificatorId, DxVosNotificationId notificationId)
{
    DX_DECLARE(DxStatus, result, DX_SUCCESS);
	DxIpAddress addr;
	DX_VOS_SetIPAddress(&addr, 127, 0, 0, 1,(DxUint16)(destNotificatorId + DX_MIN_USABLE_PORT));
	result = DX_VOS_SocketSendTo((struct _DxVosSocket*)notificator, &notificationId, sizeof(notificationId), DX_NULL, &addr);
    if (result != DX_SUCCESS)
    	RETURN_OLD_ERROR(result);
    DX_RETURN(DX_SUCCESS);
}

DxStatus DX_VOS_CreateReceiverNotificator(DxVosReceiverNotificator* notificator, DxUint32 notificatorId)
{
	DxVosSocket socket = DX_NULL;
	DX_DECLARE(DxStatus, result, DX_SUCCESS);
	DxIpAddress addr;

    DX_ASSERT_PARAM(notificator != DX_NULL);

	*notificator = DX_NULL;
	result = DX_VOS_SocketCreate(&socket, DX_AF_INET, DX_SOCK_DATAGRAM, DX_IPPROTO_UDP);
	if (result != DX_SUCCESS)
		RETURN_OLD_ERROR(result);


	DX_VOS_SetIPAddress(&addr, 127, 0, 0, 1,(DxUint16)(notificatorId + DX_MIN_USABLE_PORT));
	result = DX_VOS_SocketBind(socket, &addr);
	if (result != DX_SUCCESS)
	{
		DX_VOS_SocketClose(&socket);
		RETURN_OLD_ERROR(result);
	}
	*notificator = (DxVosSenderNotificator)socket;
    if (result != DX_SUCCESS)
    	RETURN_OLD_ERROR(result);
    DX_RETURN(DX_SUCCESS);
}

DxStatus DX_VOS_DeleteReceiverNotificator(DxVosReceiverNotificator notificator)
{
    DX_DECLARE(DxStatus, result, DX_SUCCESS);
	result = DX_VOS_SocketClose((DxVosSocket*)&notificator);
    if (result != DX_SUCCESS)
    	RETURN_OLD_ERROR(result);
    DX_RETURN(DX_SUCCESS);
}


DxStatus DX_VOS_GetNotification(DxVosReceiverNotificator notificator, DxVosNotificationId* notificationId)
{
	DxUint32 notificationSize = 0;

    DxStatus result = DX_VOS_SocketRecvFrom((struct _DxVosSocket*)notificator, notificationId, sizeof(notificationId), &notificationSize, DX_NULL, 0);
	if (result != DX_SUCCESS)
		RETURN_OLD_ERROR(result);

	if (notificationSize == 0)
		RETURN_CONST_WARNING(DX_VOS_NO_NOTIFICATION);

	if (notificationSize != sizeof(notificationId))
		RETURN_NEW_ERROR(DX_VOS_NOTIFICATION_ERROR);

	DX_RETURN(DX_SUCCESS);
}

DxStatus DX_VOS_WaitForNotification(DxVosReceiverNotificator notificator)
{
    DX_DECLARE(DxStatus, result, DX_SUCCESS);
    result = DX_VOS_SocketWaitForData((struct _DxVosSocket*)notificator, DX_INFINITE);
    if (result != DX_SUCCESS)
    	RETURN_OLD_ERROR(result);
    DX_RETURN(DX_SUCCESS);
}
