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

#ifndef Y1564_H_
#define Y1564_H_

#include <api_oam_sdk/common/types/inc/mr_api_types.h>
#include <api_oam_sdk/maintenance_association/inc/ma.h>				// needed for mdLevel_t, mdIndex_t, etc.
#include <api_oam_sdk/performance_monitoring/inc/pm.h>				// needed for dateAndTime_t
#include <api_oam_sdk/service_activation/inc/service_activation.h>
#include "egl_types.h"

#define MAX_NUM_SA_SERVICES 	(8)				// Specify the maximum number of services that can be tested simultaneously
#define MAX_NUM_CONFIG_STEPS 	(4)				// Specify the maximum number of steps that can be used in the configuration step test

typedef struct {
	uint16_t			cir;					// units are Mbps
	uint16_t			eir;					// units are Mbps
	uint16_t			cbs;					// units are kbps (not used yet!)
	uint16_t			ebs;					// units are kbps (not used yet!)
	uint16_t			frameSize;				// frame sizes to use (default = "512")
	mepIndices_t		targetMep;				// only valid if targetIsMep is true
	frameCfg_t			frameCfg;					// only valid if targetIsMep is false
	uint32_t			acceptedFrameLoss;		// units are 0.001% (default = 0)
	uint32_t			frameDelayThresh;		// units are 1us - a measured Frame Delay greater than or equal to this value will result in test fail
	uint32_t			frameDelayVarThresh;	// units are 1us - a measured Frame Delay variation greater than or equal to this value will result in test fail
	uint32_t			availabiltyThresh;		// units are 0.001% (default = 100000 == 100%)
	char				emix[6];				// Not used in this version
	int16_t				mFactor;				// units are kbps
	uint16_t			configStepSize;			// units are Mbps - default = 0 which means CIR/4 rounded up to nearest Mbps
	bool				useEmixSizes;			// If true, use packet sizes defined by the emix characters.
	bool				targetIsMep;			// Indicates if the target service is a MEP.
	bool				enable;					// Determines of this service is enabled (true) or not (false)
	bool				enPolicingTest;			// Enables the Policing test for this service
	bool				enStepTest;				// Enables the Configuration Step test for this service
	bool				enAvailability;			// Enables the measurement of availability on this service
	bool				colourAware;			// Indicates if the service is colour aware or not.
} serviceCfg_t;

typedef struct {
	uint16_t			configStepDuration;		// units are seconds (default = 60)
	uint16_t			performanceDuration;	// units are minutes (default = 15)
	saFrameType_t		frameType;
	bool				enConfigTest;			// If true configuration tests are run
	bool				runConfigInParallel;	// No yet supported - runs the config test on all services simultaneously (normal operate is in sequence)
	bool				enPerformanceTest;		// If true the performance test is run
	serviceCfg_t		serviceCfg[MAX_NUM_SA_SERVICES];
} y1564Cfg_t;

// --------------------- Configuration Test results -----------------
typedef struct {
	uint64_t			txFrameCount;
	uint64_t			rxFrameCount;
	int64_t				frameLossCount;
	uint32_t			elapsedTime;			// Units are seconds - The number of number of seconds the test has been running
	uint16_t			reserved;
	uint16_t			frameSize;				// The frame size for which these results apply
	uint32_t			frameRate;				// units are kbps - the throughput rate achieved for this packet size
	uint32_t			ulrMin;					//utilised Line Rate min in kbits/s
	uint32_t			ulrMax;
	uint32_t			ulrAvg;
	uint32_t			ulrMeasured;
	uint32_t			frameDelayMin;
	uint32_t			frameDelayMax;
	uint32_t			frameDelayAvg;
	uint32_t			frameDelayMeasured;
	uint32_t			frameDelayVarMin;
	uint32_t			frameDelayVarMax;
	uint32_t			frameDelayVarAvg;
	uint32_t			frameDelayVarMeasured;
	uint32_t			frameLossRatio;			// units are 0.001%
	uint32_t			availableSecCount;
} y1564Data_t;

typedef struct {
	y1564Data_t			dataGreen[MAX_NUM_CONFIG_STEPS];	// Fixed length array of results. Each entry has results specific to a packet size, not all entries may be valid
	y1564Data_t			dataYellow[MAX_NUM_CONFIG_STEPS];	// Fixed length array of results. Each entry has results specific to a packet size, not all entries may be valid
	testStatus_t		status[MAX_NUM_CONFIG_STEPS];		// status for each step in the test, not all entries may be valid
	bool				pass[MAX_NUM_CONFIG_STEPS];			// True if the test criteia are met, false if any test criteria fail. Not all entries may be valid
	uint8_t				steps;								// Indicates the number if steps taken so far. Corresponds to the number valid entries for dataGreen, dataYellow, status and pass
	failReason_t		failReason;							// An enumerated value that indicates the reason why a test failed. Only valid if 'pass'  is false.
} cirResults_t;

typedef struct {
	y1564Data_t			dataGreen;					// Fixed length array of results. Each entry is results specific to a packet size, not all entries may be valid
	y1564Data_t			dataYellow;					// Fixed length array of results. Each entry is results specific to a packet size, not all entries may be valid
	testStatus_t		status;						// status for each step in the test
	bool				pass;						// True if the test criteia are met, false if any test criteria fail
	failReason_t		failReason;					// An enumerated value that indicates the reason why a test failed. Only valid if 'pass'  is false.
	uint8_t				pad1b;						// present to make sizeof data struct multiple of 4 bytes
} eirResults_t;

typedef struct {
	y1564Data_t			dataGreen;					// Fixed length array of results. Each entry is results specific to a packet size, not all entries may be valid
	y1564Data_t			dataYellow;					// Fixed length array of results. Each entry is results specific to a packet size, not all entries may be valid
	testStatus_t		status;						// status for each step in the test
	bool				pass;						// True if the test criteia are met, false if any test criteria fail
	failReason_t		failReason;					// TODO: remove later if unused TBD
	uint8_t				pad1b;						// present to make sizeof data struct multiple of 4 bytes
} policerResults_t;


typedef struct {
	cirResults_t		cirResults;
	eirResults_t		eirResults;
	policerResults_t	policerResults;
	dateAndTime_t		startTime;					// Time and date that the test was started - only valid if test is enabled
	dateAndTime_t		endTime;					// Time and date that the test completed - only valid if test runs
	testStatus_t		status;						// overall status of the configuration test
} configurationResults_t;

// --------------------- Performance results -----------------

typedef struct {
	y1564Data_t			data[MAX_NUM_SA_SERVICES];			// Fixed length array of results. Each entry is results specific to a packet size, not all entries may be valid
	dateAndTime_t		startTime;							// Time and date that the test was started - only valid if test is enabled
	dateAndTime_t		endTime;							// Time and date that the test completed - only valid if test runs
	bool				pass[MAX_NUM_SA_SERVICES];			// indicates if the test has passes or not. Only valid if status is test_completed
	failReason_t		failReason[MAX_NUM_SA_SERVICES];	// An enumerated value that indicates the reason why a service failed. Only valid if 'pass'  is false.
	testStatus_t		status;								// overall status of the Performance test, not all entries may be valid
} performanceResults_t;

// --------------------- Y1564 results -----------------
typedef struct {
	configurationResults_t	configurationResults[MAX_NUM_SA_SERVICES];
	performanceResults_t	performanceResults;
} y1564Results_t;

typedef struct {
	union {
	configurationResults_t	configurationResults;
	performanceResults_t	performanceResults;
	};
} y1564SelResults_t;

typedef enum {
	sel_configuration	= 1,
	sel_performance		= 2
} testSel_t;

/**
 * @brief Configure the device to run the Y1564 tests
 *
 * @param[in] y1564Cfg this is a pointer to a y1564Cfg_t data structure that must be configured appropriately to run the tests
 * @return
 * \li  -1: Operation rejected because frameSize value is invalid
 * \li   1: Operation rejected because y1564Cfg is a NULL pointer
 * \li   2: Operation rejected because the MEP identified by 'targetMep' could not be found
 * \li   3: Operation rejected because a SA test is running.
 * \li   4: Operation successful
 *
 */
int y1564Configure(y1564Cfg_t *y1564Cfg);

/**
 * @brief Start the Y1564 tests using the current configuration
 *
 * @return
 * \li  1: Operation rejected because the port selected is down.
 * \li  2: Operation rejected because no tests are selected to run.
 * \li  3: Operation rejected because another SA test is already running.
 * \li  4: Operation successful.
 */
int y1564Start(void);

/**
 * @brief Stop the current Y1564 test
 *
 * @return
 * \li  1: Operation rejected because no Y1564 test was running.
 * \li  2: Operation successful.
 */
int y1564Stop(void);

/**
 * @brief Read the status and results for the Y1564 tests.
 *
 * @param[in] testStatus this is a pointer to a testStatus_t data type that will indicate the current state of the test suit.
 * @param[in] y1564Cfg this is a pointer to a y1564Cfg_t data struct that will be updated with the current test configuration.
 * @param[in] y1564Results this is a pointer to a y1564Results_t data struct that will be updated with any available test results.
 * @return
 * \li  1: Operation rejected because serviceIndex was an illegal value
 * \li  2: Operation rejected because testSel was an illegal value
 * \li  3: Operation succeeded
 *
 * This function can be called at any time while the tests are running or after they have completed.
 * If called while the tests are running:
 * final test results for any completed tests are provided (status = test_completed/test_failed)
 * and partial test results for actively running tests are given (status = test_running).
 * No results will be available for tests that have not yet been run but are due to be run (status = test_pending).
 * Tests that are not enabled to be run will have status = test_disabled.
 *
 */
int y1564Read(testStatus_t *testStatus, y1564Cfg_t *y1564Cfg, uint8_t serviceIndex, testSel_t testSel, y1564SelResults_t *y1564SelResults);


#endif /* Y1564_H_ */
