/*******************************************************************************
 * (c) Copyright 2015 Microsemi Corporation.  All rights reserved.
 *
 *
 *
 * SVN $Revision: $
 * SVN $Date: $
 */

#ifndef NOTIFICATIONS_H_
#define NOTIFICATIONS_H_

#include <api_oam_sdk/maintenance_association/inc/ma.h>
#include <api_oam_sdk/maintenance_domain/inc/md.h>
#include <api_oam_sdk/mep/inc/mep.h>
#include <api_oam_sdk/performance_monitoring/inc/pm.h>
#include <api_oam_sdk/rmep_db/inc/rmep_db.h>
#include <api_oam_sdk/service_activation/inc/service_activation.h>
#include "egl_types.h"

// NOTE: the API will create a Notifications Message queue at startup and will send
//        a message whenever any supported Notification event occurs.

#define NOTIFICATION_QUEUE_NAME "/notifications_q"			// The name of the Notifications Queue - use to open a 'receive' queue
#define NOTIFICATION_QUEUE_SIZE 300

#ifndef BIT_MASK
#define BIT_MASK(n) 				(0x1UL << (n < 32 ? n : (n - 32)))
#endif

typedef enum
{
	// MEF SOAM FM Notifications...
	n_cfmFaultAlarm			= 1,
	n_mepDefectAlarm		= 2,
	n_mepOperStatusAlarm	= 3,
#ifdef UNSUPPORTED_MEF_SOAM_FM_NOTIFICATIONS
	n_configErrAssertAlarm,
	n_configErrClearAlarm,
	n_lckAlarm,
	n_aisAlarm,
#endif
	// MEF SOAM PM Notifications...
#ifdef UNSUPPORTED_MEF_SOAM_PM_NOTIFICATIONS
	n_availabilityChangeAlarm,
	n_lmSessionStartStopAlarm,
	n_dmSessionStartStopAlarm,
	n_pmThresholdCrossingAlarm,
#endif
	// MEF Service EVC/UNI Notifications...
#ifdef UNSUPPORTED_MEF_SERVICE_CONFIGURATION_NOTIFICATIONS
	n_serviceConfigurationAlarm
#endif
	n_saTestCompleteAlarm
} notificationType_t;

typedef struct
{
	mdIndex_t	mdIndex;				// The Maintenance Domain Index of the MEP affected by the defect
	maIndex_t	maIndex;				// The Maintenance Association Index of the MEP affected by the defect
	mepId_t		lMepId;					// The local MEP ID of the MEP affected by the defect
	mepId_t		rMepId;					// The mepID of the remote MEP affected. This is only relevant if the defect is based on a specific MEP instance.
	fngDefect_t	highestDefect;			// The highest priority defect currently asserted when the alarm occurs, as limited by lowPrDef.
} cfmFaultAlarmInfo_t;

typedef struct
{
	mdIndex_t	mdIndex;				// The Maintenance Domain Index of the MEP affected by the defect
	maIndex_t	maIndex;				// The Maintenance Association Index of the MEP affected by the defect
	mepId_t		lMepId;					// The local MEP ID of the MEP affected by the defect
	mepId_t		rMepId;					// The mepID of the remote MEP affected. This is only relevant if the defect is based on a specific MEP instance.
	uint8_t		mepDefects;				// The current MEP defects - vector of Boolean error conditions any of which may be true (defined in mep.h)
	fngDefect_t	lastDefectSentStatus;	// The indicates the state of the previous MEP defects, mepDefects, that was sent with the previous mefSoamMepDefect notification
	rMepState_t	rMepState;				// This is only relevant if the defect is based on a specific MEP instance (rMepId != 0).
} mepDefectAlarmInfo_t;

typedef struct
{
	mdIndex_t		mdIndex;			// The Maintenance Domain Index of the MEP affected by the defect
	maIndex_t		maIndex;			// The Maintenance Association Index of the MEP affected by the defect
	mepId_t			lMepId;				// The local MEP ID of the MEP affected by the defect
	mepOpState_t	opState;			// The operational state (current capability) of the MEP
	bool			active;				//!< (e-w)Enable/disable Administrative state of MEP
} mepOperStatusAlarmInfo_t;

#ifdef UNSUPPORTED_MEF_SOAM_PM_NOTIFICATIONS
typedef struct
{
	mdIndex_t		mdIndex;			// The Maintenance Domain Index of the MEP affected by the defect
	maIndex_t		maIndex;			// The Maintenance Association Index of the MEP affected by the defect
	mepId_t			lMepId;				// The local MEP ID of the MEP affected by the defect
	pmIndex_t		pmIndex;			// The session index that experienced the threshold crossing
	crossingType_t	crossingType;		// The crossing type
	thresholdId_t	thresholdId;
	thresholdCfg_t	thresholdCfg;
	uint32_t		thresholdValue;
	objSuspect_t	objSuspect_t;
	dateAndTime_t	dateAndTime;
	macAddress_t	destMacAddress;		// The Target or Destination MAC Address Field to be transmitted. Used if destIsMepId = false.
} pmThresholdCrossingAlarmInfo_t;
#endif

#ifdef UNSUPPORTED_MEF_SERVICE_CONFIGURATION_NOTIFICATIONS
typedef enum
{
	cfg_added		= 1,
	cfg_removed		= 2,
	cfg_modified	= 3
} changeType_t;

typedef struct
{
	changeType_t	changeType;
	dateAndTime_t	dateAndTime;
} serviceConfigurationAlarmInfo_t;
#endif

// Service Activation Notifications
#define	bSaAllTestsCompete			(0)		// Value represents a bit in pmNotificationEnable bit mask. Used to enable notifications of test completion. If set, it enables: y1564AllTests, RFC2544Alltests
#define	bSaMajorTestsCompleted		(1)		// Value represents a bit in pmNotificationEnable bit mask. Used to enable notifications of test completion. If set, it enables: rfc2544ThruTest,tfc2544LatencyTest,tfc2544FrameLossTest,tfc2544Back2Backtest, y1564ConfigTest, Y1564PerfTest
#ifdef UNSUPPORTED_SERVICE_ACTIVATION_NOTIFICATIONS
#define bSaMinorTestCompleted		(2)
#endif

typedef enum
{
	rfc2544ThruTest = 1,
	rfc2544LatencyTest,
	rfc2544FrameLossTest,
	rfc2544Back2Backtest,
	rfc2544AllTests,						// This represents the 'major test' subset of: tfc2544ThruTest,tfc2544LatencyTest,tfc2544FrameLossTest,tfc2544Back2Backtest

	y1564CIRTest,
	y1564EIRTest,
	y1564Policer,
	y1564ConfigTest,						// This represents the 'minor test' subset of: y1564CIRTest,y1564EIRTest,y1564Policer
	y1564PerfTest,
	y1564AllTests							// This represents the 'major test' subset of: y1564ConfigTest, Y1564PerfTest
} saTestType_t ;

typedef struct
{
	saTestType_t	testId;					// This identifies the test or set of tests for which this notification applies
	testStatus_t	status;					// This indicates the status of the test or set of tests for which this notification applies
} saTestCompeteAlarmInfo_t;

typedef struct
{
	notificationType_t	notificationType;
	void * 				notificationPtr;		// Pointer to the notification data. !!*IMPORTANT*!!Pointer must be free'd after it is dequeue'd
} notificationMsg_t;

// Notification Enable Bit Vectors
// Defines used for setting the bits in the notificationEnable parameter
#define bCfmFaultAlarm			(0)		// 1 by default - supported and enabled
#define bMepDefectAlarm			(1)		// 1 by default - supported and enabled
#define bConfigErrorAssertAlarm	(2)		// 0 by default - NOT supported
#define bConfigErrorClearAlarm	(3)		// 0 by default - NOT supported
#define bMepOperStatusAlarm		(4)		// 1 by default - supported and enabled
#define bLckAlarm				(5)		// 0 by default - NOT supported
#define bAisAlarm				(6)		// 0 by default - NOT supported

void createNotificationQueue(void);

/**
 * @brief Sends a Notification Message into the Notifications queue
 */
int sendNotification(notificationType_t type, void *notificationInfo);

/**
 * @brief Sets the CFM notifications configuration values
 *
 * @param notificationIntervalVal The interval in seconds (0 to 60) between two consecutive notifications of the same type. FIXED at 0 in this revision!
 * @param notificationEnableVal A vector of bits to enable (=1) or disable(=0) specific notifications. (see the section above 'Notification Enable Bit Vectors' for details of the bits)
 * @returns 1 if successful, 0 if an invalid value is used.
 */
int setCfmNotificationCfg(uint32_t notificationIntervalVal, uint32_t notificationEnableVal);

/**
 * @brief Gets the current CFM notifications configuration values
 *
 * @param notificationIntervalPte A pointer to uint32_t which returns the interval in seconds (0 to 60) between two consecutive notifications of the same type. FIXED at 0 in this revision!
 * @param notificationEnablePtr A pointer to uint32_t which returns a vector of bits tindicating which specific notifications are enabled (=1) or disabled(=0). (see the section above 'Notification Enable Bit Vectors' for details of the bits)

 */
void getCfmNotificationCfg(uint32_t *notificationIntervalPtr, uint32_t *notificationEnablePtr);

void sendCfmFaultNotification(lMepNum_t lMepNum, mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, mepId_t rMepId, uint16_t log_handle, uint8_t highestDefect);
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);
void sendMepOpStateNotification(lMepNum_t lMepNum, mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, uint16_t log_handle, bool active, mepOpState_t opState);


/**
 * @brief Sets/clears the Enables bits for controlling which Service Activation test notifications are active
 *
 * @param notificationEnableVal A vector of bits to enable (=1) or disable(=0) specific notifications. (see the section above 'Service Activation Notifications' for details of the bits)
 * @returns 1 if successful, 0 if an invalid value is used.
 *
 * Notifications for Service Activation tests are not enabled by default. They must be enabled using this command.
 * Two levels of notification are currently supported. They are enabled by setting the bits: bSaAllTestsCompete and/or bSaMajorTestsCompleted
 * if bSaAllTestsCompete is set then a notification will be sent when the full y1564 or full RFC2544Alltests suite is completed.
 * f bSaAllTestsCompete is set then a notification will be sent when the each of the 'sub-tests' in a test suits is completed.
 * i.e. for RFC2544 this is Throughput,Latency,FrameLoss and Back2Back and for y1564 it is Configuration and Performance tests.
 */
int setSaNotificationCfg(uint32_t notificationEnableVal);

/**
 * @brief This function will send a Service Activation notification to the notification queue
 *
 * This function is generally only called from within the API
 */
void sendSaStatusNotificaiton(uint16_t log_handle, saTestType_t	testId, testStatus_t status);

#endif /* NOTIFICATIONS_H_ */
