/*
 * egl_notifications.c
 *
 *  Created on: 4 Jan 2016
 *      Author: nfdonovan
 */

#include <api_oam_sdk/mep/src/mep_types.h>
#include <api_oam_sdk/notifications/inc/egl_notifications.h>
#include "egl_assert.h"
#include "osal.h"

osQueueHandle_t notificationsQueue = NULL;

static uint32_t	cfmNotificationInterval = 0;
static uint32_t	cfmNotificationEnable = 0;
static uint32_t	saNotificationEnable = 0;

#define SUPPORTED_CFM_NOTIFICATIONS_BIT_MASK	(BIT_MASK(bCfmFaultAlarm) | BIT_MASK(bMepDefectAlarm) | BIT_MASK(bMepOperStatusAlarm))
#define SUPPORTED_SA_NOTIFICATIONS_BIT_MASK		(BIT_MASK(bSaAllTestsCompete) | BIT_MASK(bSaMajorTestsCompleted))

void createNotificationQueue(void)
{
#ifndef FREERTOS
	if (notificationsQueue == NULL)
	{
		notificationsQueue = osCreateQueueByName(NOTIFICATION_QUEUE_SIZE,sizeof(notificationMsg_t),NOTIFICATION_QUEUE_NAME);
	}
	ASSERT_NOT_NULL(notificationsQueue);
#endif
}


void getCfmNotificationCfg(uint32_t *notificationIntervalPtr, uint32_t *notificationEnablePtr)
{
	if (notificationIntervalPtr != NULL)
	{
		*notificationIntervalPtr = cfmNotificationInterval;
	}
	if (notificationEnablePtr != NULL)
	{
		*notificationEnablePtr = cfmNotificationEnable;
	}
}

int setCfmNotificationCfg(uint32_t notificationIntervalVal, uint32_t notificationEnableVal)
{
#if NOTIFICATION_INTERVAL_SUPPORTED
	if (notificationIntervalVal <= 60)
	{
		cfmNotificationInterval = notificationIntervalVal;
	}
	else
	{
		cfmNotificationInterval = 60;
	}
#endif

	cfmNotificationEnable = notificationEnableVal & SUPPORTED_CFM_NOTIFICATIONS_BIT_MASK;

	return (1);
}

/**
 * @brief Sends the notification info provided to the notifications message queue
 * @returns 1 if successful, 0 if there is a problem
 */
int sendNotification(notificationType_t type, void *notificationInfo)
{
	notificationMsg_t notificationMsg;

#ifdef FREERTOS
	return(1);
#else
	ASSERT_NOT_NULL(notificationInfo);
	ASSERT_NOT_NULL(notificationsQueue);

	notificationMsg.notificationType	= type;
	notificationMsg.notificationPtr		= notificationInfo;
	return (osQueueSend(notificationsQueue, &notificationMsg, 0));

#endif
}


void sendCfmFaultNotification(lMepNum_t lMepNum, mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, mepId_t rMepId, uint16_t log_handle, uint8_t highestDefect)
{
	cfmFaultAlarmInfo_t	*cfmFaultAlarmInfo;

	// Only send the notification if enabled to do so...
	if (cfmNotificationEnable & BIT_MASK(bCfmFaultAlarm))
	{
		cfmFaultAlarmInfo = ts_malloc(sizeof(cfmFaultAlarmInfo_t));
		if (cfmFaultAlarmInfo == NULL)
		{
			DO_LOG_ERROR(log_handle,"Failed to send cfmFaultAlarm to notifications queue - out of RAM");
			return;
		}
		cfmFaultAlarmInfo->mdIndex					= mdIndex;
		cfmFaultAlarmInfo->maIndex					= maIndex;
		cfmFaultAlarmInfo->lMepId					= lMepId;
		cfmFaultAlarmInfo->rMepId					= rMepId;
		cfmFaultAlarmInfo->highestDefect			= highestDefect;
		if (sendNotification(n_cfmFaultAlarm,(void*) cfmFaultAlarmInfo) != 1)
		{
			DO_LOG_ERROR(log_handle,"Failed to add cfmFaultAlarm to notifications queue");
		}
	}
}

void sendMepDefectNotification(lMepNum_t lMepNum, mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, mepId_t rMepId, uint16_t log_handle, uint8_t mepDefects, uint8_t lastDefectStatus, rMepState_t rMepState)
{
	mepDefectAlarmInfo_t	*mepDefectAlarmInfo;

	// Only send the notification if enabled to do so...
	if (cfmNotificationEnable& BIT_MASK(bMepDefectAlarm))
	{
		mepDefectAlarmInfo = ts_malloc(sizeof(mepDefectAlarmInfo_t));
		if (mepDefectAlarmInfo == NULL)
		{
			DO_LOG_ERROR(log_handle,"Failed to send mepDefectAlarm to notifications queue - out of RAM");
			return;
		}
		mepDefectAlarmInfo->mdIndex					= mdIndex;
		mepDefectAlarmInfo->maIndex					= maIndex;
		mepDefectAlarmInfo->lMepId					= lMepId;
		mepDefectAlarmInfo->rMepId					= rMepId;
		mepDefectAlarmInfo->mepDefects				= mepDefects;
		mepDefectAlarmInfo->lastDefectSentStatus	= lastDefectStatus;
		mepDefectAlarmInfo->rMepState				= rMepState;

		if (sendNotification(n_mepDefectAlarm,(void*) mepDefectAlarmInfo) != 1)
		{
			DO_LOG_ERROR(log_handle,"Failed to add mepDefectAlarm to notifications queue");
		}
	}
}

void sendMepOpStateNotification(lMepNum_t lMepNum, mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, uint16_t log_handle, bool active, mepOpState_t opState)
{
	mepOperStatusAlarmInfo_t	*mepOperStatusAlarmInfo;

	// Only send the notification if enabled to do so...
	if (cfmNotificationEnable & BIT_MASK(bMepOperStatusAlarm))
	{
		mepOperStatusAlarmInfo = ts_malloc(sizeof(mepOperStatusAlarmInfo_t));
		if (mepOperStatusAlarmInfo == NULL)
		{
			DO_LOG_ERROR(log_handle,"Failed to send mepOperStatusAlarm to notifications queue - out of RAM");
			return;
		}
		mepOperStatusAlarmInfo->mdIndex		= mdIndex;
		mepOperStatusAlarmInfo->maIndex		= maIndex;
		mepOperStatusAlarmInfo->lMepId		= lMepId;
		mepOperStatusAlarmInfo->active		= active;
		mepOperStatusAlarmInfo->opState		= opState;

		if (sendNotification(n_mepOperStatusAlarm,(void*) mepOperStatusAlarmInfo) != 1)
		{
			DO_LOG_ERROR(log_handle,"Failed to add mepOperStatusAlarm to notifications queue");
		}
	}
}

int setSaNotificationCfg(uint32_t notificationEnableVal)
{
	saNotificationEnable = notificationEnableVal & SUPPORTED_SA_NOTIFICATIONS_BIT_MASK;

	return (1);
}

void getSaNotificationCfg(uint32_t *notificationEnablePtr)
{
	if (notificationEnablePtr != NULL)
	{
		*notificationEnablePtr = saNotificationEnable;
	}
}

void sendSaStatusNotificaiton(uint16_t log_handle, saTestType_t	testId, testStatus_t status)
{
	saTestCompeteAlarmInfo_t	*saTestCompeteAlarmInfo;

	// Only send the notification if enabled to do so...
	if (
		((saNotificationEnable & BIT_MASK(bSaAllTestsCompete)) && ((testId == rfc2544AllTests) || (testId == y1564AllTests))) ||					// if notification is enabled for a 'all' tests and the testId is match
		((saNotificationEnable & BIT_MASK(bSaMajorTestsCompleted)) && ((testId == rfc2544ThruTest) || (testId == rfc2544LatencyTest) ||				// or if notification is enabled for a 'major' tests and testId is a match
				(testId == rfc2544FrameLossTest) || (testId == rfc2544Back2Backtest) || (testId == y1564ConfigTest) || (testId == y1564PerfTest)))
	)
	{
		saTestCompeteAlarmInfo = ts_malloc(sizeof(saTestCompeteAlarmInfo_t));//mm
		if (saTestCompeteAlarmInfo == NULL)
		{
			DO_LOG_ERROR(log_handle,"Failed to send saTestCompleteAlarm to notifications queue - out of RAM");
			return;
		}
		saTestCompeteAlarmInfo->testId					= testId;
		saTestCompeteAlarmInfo->status					= status;

		if (sendNotification(n_saTestCompleteAlarm,(void*) saTestCompeteAlarmInfo) != 1)
		{
			DO_LOG_ERROR(log_handle,"Failed to add saTestCompleteAlarm to notifications queue");
		}
	}
}
