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

#ifndef PM_DM_H_
#define PM_DM_H_


#include <api_oam_sdk/common/types/inc/mr_api_types.h>
#include <api_oam_sdk/maintenance_association/inc/ma.h>
#include <api_oam_sdk/performance_monitoring/inc/pm.h>
#include "egl_types.h"

typedef enum
{
	dmDmm	= 1,	// DMM SOAM PDU generated, DMR responses received(one-way or two-way measurements)
	dm1DmTx	= 2,	// 1DM SOAM PDU generated (one-way measurements are made bythe receiver)
	dm1DmRx	= 3		// 1DM SOAM PDU received and tracked (one-way measurements)
} delayType_t;

typedef enum
{
	bt_twoWayFrameDelay			= 1,
	bt_forwardFrameDelay		= 2,
	bt_backwardFrameDelay		= 3,
	bt_twoWayIfdv				= 4,
	bt_forwardIfdv				= 5,
	bt_backwardIfdv				= 6,
	bt_twoWayFrameDelayRange	= 7,
	bt_forwardFrameDelayRange	= 8,
	bt_backwardFrameDelayRange	= 9
} dmBinType_t;

typedef struct
{
	uint32_t			numMeasBinsPerFrameDelayInterval;			// (default=3) specifies the number of measurement bins per Measurement Interval for Frame Delay measurements. At least 3 bins are to be supported
	uint32_t			numMeasBinsPerInterFrameDelayVariationInterval;// (default=2) specifies the number of measurement bins per Measurement Interval for Inter-Frame Delay Variation measurements. The minimum number is 2
	uint32_t			interFrameDelayVariationSelectionOffset;	// (default=1) specifies the selection offset for Inter-Frame Delay Variation measurements
	uint32_t			numMeasBinsPerFrameDelayRangeInterval;		// (default=2) specifies the number of measurement bins per Measurement Interval for Frame Delay Range measurements. The minimum number is 2
	struct	pmConfig_s	cfg;
	macAddress_t		sourceMacAddress;							// The Source MAC Address Field of the received SOAM DM session PDUs. If mefSoamDmCfgType is dm1DmRx this object indicates the source address of the dm1DmTx DM session
	delayType_t			type;										// specifies what type of Delay Measurement will be performed
} dmCfg_t;

// The bit vectors used to access/modify measurementEnable in pmConfig_s
#define bDmSoamPdusSent						(0)		// 0
#define bDmSoamPdusReceived					(1)		// 1
#define bFrameDelayTwoWayBins				(2)		// 1
#define bFrameDelayTwoWayMin				(3)		// 1
#define bFrameDelayTwoWayMax				(4)		// 1
#define bFrameDelayTwoWayAvg				(5)		// 1
#define bFrameDelayForwardBins				(6)		// 0
#define bFrameDelayForwardMin				(7)		// 0
#define bFrameDelayForwardMax				(8)		// 0
#define bFrameDelayForwardAvg				(9)		// 0
#define bFrameDelayBackwardBins				(10)	// 0
#define bFrameDelayBackwardMin				(11)	// 0
#define bFrameDelayBackwardMax				(12)	// 0
#define bFrameDelayBackwardAvg				(13)	// 0
#define bIfdvForwardBins					(14)	// 0
#define bIfdvForwardMin						(15)	// 0
#define bIfdvForwardMax						(16)	// 0
#define bIfdvForwardAvg						(17)	// 0
#define bIfdvBackwardBins					(18)	// 0
#define bIfdvBackwardMin					(19)	// 0
#define bIfdvBackwardMax					(20)	// 0
#define bIfdvBackwardAvg					(21)	// 0
#define bIfdvTwoWayBins						(22)	// 1
#define bIfdvTwoWayMin						(23)	// 1
#define bIfdvTwoWayMax						(24)	// 1
#define bIfdvTwoWayAvg						(25)	// 1
#define bFrameDelayRangeForwardBins			(26)	// 0
#define bFrameDelayRangeForwardMax			(27)	// 0
#define bFrameDelayRangeForwardAvg			(28)	// 0
#define bFrameDelayRangeBackwardBins		(29)	// 0
#define bFrameDelayRangeBackwardMax			(30)	// 0
#define bFrameDelayRangeBackwardAvg			(31)	// 0
#define bFrameDelayRangeTwoWayBins			(32)	// 0
#define bFrameDelayRangeTwoWayMax			(33)	// 0
#define bFrameDelayRangeTwoWayAvg			(34)	// 0
#define bMeasuredStatsFrameDelayTwoWay		(35)	// 1
#define bMeasuredStatsFrameDelayForward		(36)	// 0
#define bMeasuredStatsFrameDelayBackward	(37)	// 0
#define bMeasuredStatsIfdvTwoWay			(38)	// 1
#define bMeasuredStatsIfdvForward			(39)	// 0
#define bMeasuredStatsIfdvBackward			(40)	// 0
#define delayMeasurementEnableDefaultLower	(0x03C0003E)
#define delayMeasurementEnableDefaultUpper	(0x00000048)

typedef uint32_t	dmCfgMeasBin_t[10][5];		// support 4 bins for each bin type (5 bin thresholds)

typedef struct
{
	uint32_t	frameDelayTwoWay;				// The two-way frame delay calculated by this MEP from the last received SOAM PDU
	uint32_t	frameDelayForward;				// The frame delay in the forward direction calculated by this MEP from the last received SOAM PDU
	uint32_t	frameDelayBackward;				// The frame delay in the backward direction calculated by this MEP from the last received SOAM PDU
	uint32_t	ifdvTwoWay;						// The last two-way inter-frame delay interval calculated by this MEP
	uint32_t	ifdvForward;					// The last one-way inter-frame delay interval in the forward direction calculated by this MEP
	uint32_t	ifdvBackward;					// The last one-way inter-frame delay interval in the backward direction calculated by this MEP
} dmMeasuredStats_t;

typedef struct
{
	uint32_t		index;						// The index for the current Measurement Interval for this PM session
	dateAndTime_t	startTime;					// The time that the current Measurement Interval started
	timeInterval_t	elapsedTime;				// The time that the current Measurement Interval has been running, in 0.01 seconds
	uint32_t		frameDelayTwoWayMin;		// The minimum two-way frame delay calculated by this MEP for this Measurement Interval
	uint32_t		frameDelayTwoWayMax;		// The maximum two-way frame delay calculated by this MEP for this Measurement Interval
	uint32_t		frameDelayTwoWayAvg;		// The average two-way frame delay calculated by this MEP for this Measurement Interval
	uint32_t		frameDelayForwardMin;		// The minimum one-way frame delay in the forward direction calculated by this MEP for this Measurement Interval
	uint32_t		frameDelayForwardMax;		// The maximum one-way frame delay in the forward direction calculated by this MEP for this Measurement Interval
	uint32_t		frameDelayForwardAvg;		// The average one-way frame delay in the forward direction calculated by this MEP for this Measurement Interval
	uint32_t		frameDelayBackwardMin;		// The minimum one-way frame delay in the backward direction calculated by this MEP for this Measurement Interval
	uint32_t		frameDelayBackwardMax;		// The maximum one-way frame delay in the backward direction calculated by this MEP for this Measurement Interval
	uint32_t		frameDelayBackwardAvg;		// The average one-way frame delay in the backward direction calculated by this MEP for this Measurement Interval
	uint32_t		ifdvForwardMin;				// The minimum one-way inter-frame delay interval in the forward direction calculated by this MEP for this Measurement Interval
	uint32_t		ifdvForwardMax;				// The maximum one-way inter-frame delay interval in the forward direction calculated by this MEP for this Measurement Interval
	uint32_t		ifdvForwardAvg;				// The average one-way inter-frame delay interval in the forward direction calculated by this MEP for this Measurement Interval
	uint32_t		ifdvBackwardMin;			// The minimum one-way inter-frame delay interval in the backward direction calculated by this MEP for this Measurement Interval
	uint32_t		ifdvBackwardMax;			// The maximum one-way inter-frame delay interval in the backward direction calculated by this MEP for this Measurement Interval
	uint32_t		ifdvBackwardAvg;			// The average one-way inter-frame delay interval in the backward direction calculated by this MEP for this Measurement Interval
	uint32_t		ifdvTwoWayMin;				// The minimum two-way inter-frame delay interval calculated by this MEP for this Measurement Interval
	uint32_t		ifdvTwoWayMax;				// The maximum two-way inter-frame delay interval calculated by this MEP for this Measurement Interval
	uint32_t		ifdvTwoWayAvg;				// The average two-way inter-frame delay interval calculated by this MEP for this Measurement Interval
	uint32_t		frameDelayRangeForwardMax;	// The maximum one-way frame delay range in the forward direction calculated by this MEP for this Measurement Interval
	uint32_t		frameDelayRangeForwardAvg;	// The average one-way frame delay range in the forward direction calculated by this MEP for this Measurement Interval
	uint32_t		frameDelayRangeBackwardMax;	// The maximum one-way frame delay range in the backward direction calculated by this MEP for this Measurement Interval
	uint32_t		frameDelayRangeBackwardAvg;	// The average one-way frame delay range in the backward direction calculated by this MEP for this Measurement Interval
	uint32_t		frameDelayRangeTwoWayMax;	// The maximum two-way frame delay range calculated by this MEP for this Measurement Interval
	uint32_t		frameDelayRangeTwoWayAvg;	// The average two-way frame delay range calculated by this MEP for this Measurement Interval
	gauge32_t		soamPdusSent;				// contains the count of the number of SOAM PDUs sent during this Measurement Interval
	gauge32_t		soamPdusReceived;			// contains the count of the number of SOAM PDUs PDUs received in this Measurement Interval
	bool			suspect;					// Whether the Measurement Interval has been marked as suspect
} dmStats_t;

typedef uint32_t	dmStatsBins_t[10][4];		// support 4 bins for each bin type



typedef struct
{
	bitVector32_t	enable;
	uint32_t		measuredFrameDelayTwoWayThreshold;
	uint32_t		maxFrameDelayTwoWayThreshold;
	uint32_t		avgFrameDelayTwoWayThreshold;
	uint32_t		measuredIfdvTwoWayThreshold;
	uint32_t		maxIfdvTwoWayThreshold;
	uint32_t		avgIfdvTwoWayThreshold;
	uint32_t		maxFrameDelayRangeTwoWayThreshold;
	uint32_t		avgFrameDelayRangeTwoWayThreshold;
	uint32_t		measuredFrameDelayForwardThreshold;
	uint32_t		maxFrameDelayForwardThreshold;
	uint32_t		avgFrameDelayForwardThreshold;
	uint32_t		measuredIfdvForwardThreshold;
	uint32_t		maxIfdvForwardThreshold;
	uint32_t		avgIfdvForwardThreshold;
	uint32_t		maxFrameDelayRangeForwardThreshold;
	uint32_t		avgFrameDelayRangeForwardThreshold;
	uint32_t		measuredFrameDelayBackwardThreshold;
	uint32_t		maxFrameDelayBackwardThreshold;
	uint32_t		avgFrameDelayBackwardThreshold;
	uint32_t		measuredIfdvBackwardThreshold;
	uint32_t		maxIfdvBackwardThreshold;
	uint32_t		avgIfdvBackwardThreshold;
	uint32_t		maxFrameDelayRangeBackwardThreshold;
	uint32_t		avgFrameDelayRangeBackwardThreshold;
} dmThresholdCfg_t;

// The bit vectors used to access/modify enable in dmThresholdCfg_t
// NOTE Frame Delay = FD
#define bDmMeasuredFDTwoWayThres		(0)
#define bDmMaxFDTwoWayThres				(1)
#define bDmAvgFDTwoWayThres				(2)
#define bDmMeasuredIfdvTwoWayThres		(3)
#define bDmMaxIfdvTwoWayThres			(4)
#define bDmAvgIfdvTwoWayThres			(5)
#define bDmMaxFDRangeTwoWayThres		(6)
#define bDmAvgFDRangeTwoWayThres		(7)
#define bDmMeasuredFDForwardThres		(8)
#define bDmMaxFDForwardThres			(9)
#define bDmAvgFDForwardThres			(10)
#define bDmMeasuredIfdvForwardThres		(11)
#define bDmMaxIfdvForwardThres			(12)
#define bDmAvgIfdvForwardThres			(13)
#define bDmMaxFDRangeForwardThres		(14)
#define bDmAvgFDRangeForwardThres		(15)
#define bDmMeasuredFDBackwardThres		(16)
#define bDmMaxFDBackwardThres			(17)
#define bDmAvgFDBackwardThres			(18)
#define bDmMeasuredIfdvBackwardThres	(19)
#define bDmMaxIfdvBackwardThres			(20)
#define bDmAvgIfdvBackwardThres			(21)
#define bDmMaxFDRangeBackwardThres		(22)
#define bDmAvgFDRangeBackwardThres		(23)

/**
 * @brief Sets default values for the Delay Configuration settings
 */
void pmSetDmCfgDefaults(dmCfg_t *dmCfg);

/**
 * @brief Sets default values for the Delay Bins settings
 */
void pmSetDmDefaultBins(dmCfgMeasBin_t	dmCfgMeasBin);

/**
 * @brief Sets default values for the Delay Threshold settings
 */
void pmSetDmThresholdDefaults(dmThresholdCfg_t	*dmThresholdCfg);

/**
 * @brief Read the next entry in the Delay Session List
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the parent MA
 * @param[in] lMepId is the local MEPID
 * @param[in] nextLmIndex is 0 or a valid Delay Session index for this MEP
 * @return	Index of the next Delay Session or 0 if no more entries
 *
 * Read the next entry in the Delay  Service List for the selected local MEP.
 * If nextLmIndex is 0 it returns the Delay Index of the first session or 0 if
 * there are no sessions on the MEP. If a valid Delay Index is provided for
 * nextDmIndex the function returns the Delay Index of the next session in the
 * list or 0 if the end of the list has been reached.
 */
pmIndex_t delayMeasurementReadList(mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, pmIndex_t nextDmIndex);

/**
 * @brief Create a Delay Session using the configuration provided
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the parent MA
 * @param[in] lMepId is the local MEPID
 * @param[in] dmIndex is the index to use for the new Delay Session
 * @param[in] dmCfg is a pointer to a dmCfg_t data struct that provides the configuration info for the session
 * @param[in] dmThresholdCfg is a pointer to a dmThresholdCfg_t data struct that provides the threshold info for the session
 * @param[in] dmCfgMeasBin is a pointer to a dmCfgMeasBin_t data struct that provides the delay bins info for the session
 * @return
 * \li	-1: Operation rejected due to insufficient resources
 * \li	 1: Operation rejected because the supplied Index is invalid
 * \li	 2: Operation rejected because one or more Delay Bins or Threshold Configuration values are not supported
 * \li	 3: Operation rejected due to invalid configuration value.
 * \li	 4: Operation accepted.
 */
int delayMeasurementCreate(mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, pmIndex_t dmIndex,dmCfg_t *dmCfg,dmThresholdCfg_t *dmThresholdCfg, dmCfgMeasBin_t dmCfgMeasBin);

/**
 * @brief Remove the specified Delay Session from the specified MEP
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the parent MA
 * @param[in] lMepId is the local MEPID
 * @param[in] dmIndex is a valid Delay Session index for this MEP
 * @return
 * \li  1: Operation rejected because the supplied Delay Measurement Index is invalid
 * \li  2: Operation accepted
 *
 * Remove the specified Delay Session from the specified MEP
 */
int delayMeasurementDelete(mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, pmIndex_t dmIndex);

/**
 * @brief Read the measurement values for a specified delay session
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the parent MA
 * @param[in] lMepId is the local MEPID
 * @param[in] dmIndex is the Delay Session index for this MEP
 * @param[in] dmCfg is a pointer to a lmCfg_t data type. If the value is not NULL it is updated with the delay configuration
 * @param[in] measuredStats is a pointer to a dmMeasuredStats_t data type. If the value is not NULL it is updated with the last measured delay values
 * @param[in] currentStats is a pointer to a dmStats_t data type. If the value is not NULL it is updated with the current measured delay values
 * @param[in] currenStatsBins is a pointer to a dmStatsBins_t data type. If the value is not NULL it is updated with the current measured delay bins values
 * @param[in] thresholdCfg is a pointer to a dmThresholdCfg_t data type. If the value is not NULL it is updated with the configured Threshold values
 * @param[in] dmCfgMeasBin is a pointer to a dmCfgMeasBin_t data type. If the value is not NULL it is updated with the configured Bins Threshold values
 *
 * @return
 * \li  1: Operation rejected because the supplied Delay Measurement Index is invalid
 * \li  2: Operation accepted
 */
int delayMeasurementRead(mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, pmIndex_t dmIndex,
		dmCfg_t				*dmCfg,
		dmMeasuredStats_t	*measuredStats,
		dmStats_t			*currentStats,
		dmStatsBins_t		currenStatsBins,
		dmThresholdCfg_t	*thresholdCfg,
		dmCfgMeasBin_t 		dmCfgMeasBin);

/**
 * @brief Read the Delay bins History at the specified measurement index for a specified Delay Session
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the parent MA
 * @param[in] lMepId is the local MEPID
 * @param[in] dmIndex is the Delay Session index for this MEP
 * @param[in] statsIndex is the index value used to select a saved interval
 * @param[in] historyStatsBins is a pointer to a dmStatsBins_t data type that is updated with the history stats bins for the selected interval

 * @return
 * \li	-1: Operation rejected because the supplied Delay Measurement history Stats bins pointer is NULL
 * \li   1: Operation rejected because the supplied Delay Measurement Index is invalid
 * \li   2: Operation rejected because the supplied Delay Measurement history Availability Stats Index is invalid
 * \li   3: Operation accepted
 */
int delayMeasurementReadHistoryStatsBins(mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, pmIndex_t dmIndex,
		uint32_t			statsIndex,
		dmStatsBins_t		historyStatsBins);

/**
 * @brief Read the Delay History at the specified measurement index for a specified Delay Session
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the parent MA
 * @param[in] lMepId is the local MEPID
 * @param[in] lmIndex is the Delay Session index for this MEP
 * @param[in] statsIndex is the index value used to select a saved interval
 * @param[in] historyStats is a pointer to a dmStats_t data type that is updated with the history stats for the selected interval
 * @return
 * \li	-1: Operation rejected because the supplied Delay Measurement historyStats pointer is NULL
 * \li   1: Operation rejected because the supplied Delay Measurement Index is invalid
 * \li   2: Operation rejected because the supplied Delay Measurement history Stats Index is invalid
 * \li   3: Operation accepted
 */
int delayMeasurementReadHistoryStats(mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, pmIndex_t dmIndex,
		uint32_t			statsIndex,
		dmStats_t			*historyStats);

/**
 * @brief Enable/disable a specified Delay Session. This starts and stops the session.
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the parent MA
 * @param[in] lMepId is the local MEPID
 * @param[in] dmIndex is a valid Delay Session index for this MEP
 * @param[in] enable is used to enable (true) or disable (false) the Delay measurement session
 * @return
 * \li  1: Operation rejected because the supplied Delay Measurement Index is invalid
 * \li  2: Operation accepted
 */
int delayMeasurementEnable(mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, pmIndex_t dmIndex, bool enable);

/**
 * @brief This will clear any saved Delay history for the specified Delay session
 *
 * @param[in] mdIndex of the parent MD
 * @param[in] maIndex of the parent MA
 * @param[in] lMepId is the local MEPID
 * @param[in] dmIndex is the Delay Session index for this MEP
 * @return
 * \li  1: Operation rejected because the supplied Delay Measurement Index is invalid
 * \li  2: Operation accepted
 */
int delayMeasurementClearHistory(mdIndex_t mdIndex, maIndex_t maIndex, mepId_t lMepId, pmIndex_t dmIndex);

#endif /* PM_DM_H_ */
