/******************************************************************************
** 文件名:  WholeLineScreenAPI.c
** 描 述:   全线免筛模块对外接口实现
*******************************************************************************/
#include "WholeLineScreenAPI.h"
#include "WLScreenDataManage.h"
#include "WLScreenDataPrepare.h"
#include "CommonMemory.h"
#include "WLScreenLogicProcess.h"
#include "SystemConfigDefine.h"



/**
 * @brief 对外接口：打印全线免筛信息 
 * @param[in] 无
 * @param[out] 无
 * @return 无
 * @note 无
 */
void wls_PrintfWLScreenInfo(void)
{
	UINT16 cycle = 0u;
	UINT8 cycleAC = 0u;
	UINT8 UTACCnt = 0u;
	UINT16 tmpACID = 0u;
	const WLSreenInfoStruct* pTemp = NULL;
	const WLTrainStatusInfoStruct* pTrainInfo = NULL;
	UINT16 outStringLength = 0u;
	UINT8 outwlsString[MAX_WLS_LOG_NUM] = { 0U };
	UINT8 lastTrainNum = 0U;
	UINT16 lastTrainDress = 0U;
	UINT8 curTrainNum = 0U;
	UINT16 curTrainDress = 0U;

	/** 获取全线免筛信息的地址 不会返回NULL*/
	pTemp = wls_GetWholeLineScreeInfo();

	LongToChar(pTemp->sendSeq, &outwlsString[outStringLength]);
	outStringLength += 4U;
	LongToChar(pTemp->recvSeq, &outwlsString[outStringLength]);
	outStringLength += 4U;
	outwlsString[outStringLength++] = pTemp->WLScreenProcessFlag;
	outwlsString[outStringLength++] = pTemp->WLScreenVaildFlag;
	outwlsString[outStringLength++] = pTemp->UTFlag;
	outwlsString[outStringLength++] = pTemp->enterCheckFlag;
	outwlsString[outStringLength++] = (UINT8)pTemp->redunTime;
	lastTrainDress = outStringLength;
	outStringLength++;			/*存下lasttrain数量*/

	for (cycle = 1u; cycle < LINE_MAX_TRAIN; cycle++)
	{
		pTrainInfo = wls_GetLastTrainStatusInfo(cycle);

		if ((NULL != pTrainInfo) && (OUT_CONTROL_STATUS != pTrainInfo->controlStatus))
		{
			lastTrainNum++;
			ShortToChar(cycle, &outwlsString[outStringLength]);
			outStringLength += 2U;
			outwlsString[outStringLength++] = pTrainInfo->controlStatus;
			outwlsString[outStringLength++] = pTrainInfo->headNeedScreen;
			outwlsString[outStringLength++] = pTrainInfo->tailNeedScreen;
		}
		else
		{
			/** 非控车，不打印 */
		}
	}
	outwlsString[lastTrainDress] = lastTrainNum;

	curTrainDress = outStringLength;
	outStringLength++;			/*存下curTrain数量*/

	for (cycle = 1u; cycle < LINE_MAX_TRAIN; cycle++)
	{
		pTrainInfo = wls_GetCurTrainStatusInfo(cycle);

		if ((NULL != pTrainInfo) && (OUT_CONTROL_STATUS != pTrainInfo->controlStatus))
		{
			curTrainNum++;
			ShortToChar(cycle, &outwlsString[outStringLength]);
			outStringLength += 2U;
			outwlsString[outStringLength++] = pTrainInfo->controlStatus;
			outwlsString[outStringLength++] = pTrainInfo->headNeedScreen;
			outwlsString[outStringLength++] = pTrainInfo->tailNeedScreen;
		}
		else
		{
			/** 非控车，不打印 */
		}
	}
	outwlsString[curTrainDress] = curTrainNum;

	/* 打印UT计轴ID */
	UTACCnt = wls_GetUTACCnt();

	outwlsString[outStringLength++] = UTACCnt;

	for (cycleAC = 0u; cycleAC < UTACCnt; cycleAC++)
	{
		tmpACID = wls_GetUTACId(cycleAC);
		ShortToChar(tmpACID, &outwlsString[outStringLength]);
		outStringLength += 2U;
	}


	if (outStringLength == 0u)
	{
	}
	else
	{
#ifdef PLATFORM_2OO2
		debug_infor_printf((const)"\nWLSScreeData:%d\nsendseq(4)-recvSeq(4)-WLScreenProcessFlag-WLScreenVaildFlag-UTFlag-enterCheckFlag-redunTime-lastTrainNum-cycle-controlStatus-headNeedScreen-tailNeedScreen-curTrainNum-cycle-controlStatus-headNeedScreen-tailNeedScreen-UTACCnt-tmpACID",  outStringLength);

		debug_out_array(0xAA, outwlsString, outStringLength);
#endif

#ifdef PLATFORM_LABVIEW_DEBUG

		Out_Array_Buffer(0, "\nWLSScreeData:%d", outStringLength);
		Out_Array_Buffer(0, "nsendseq(4)-recvSeq(4)-WLScreenProcessFlag-WLScreenVaildFlag-UTFlag-enterCheckFlag-redunTime-lastTrainNum-cycle-controlStatus-headNeedScreen-tailNeedScreen-curTrainNum-cycle-controlStatus-headNeedScreen-tailNeedScreen-UTACCnt-tmpACID:%d", outStringLength);
		Out_Array_Buffer(16, outwlsString, outStringLength);

#endif
	}
}


/**
 * @brief 对外接口：全线免筛模块初始化
 * @param[in] 无
 * @param[out] 无
 * @return 无
 * @note CI_ERROR,初始化失败；CI_SUCCESS,初始化成功
 */
UINT8 wls_Init(void)
{
	UINT8 ret = CI_ERROR;
	UINT32 errorCode = 0u;
	UINT8 funRet = CI_ERROR;
	UINT8 cycleAC = 0u;
	UINT16 cycle = 0u;
	UINT32 redunTime = 0u;
	WLTrainStatusInfoStruct tmpTrainInfo = {0u};

	wls_SetSendSeq(0u);
	wls_SetRecvSeq(0u);

	wls_SetWLScreenProcessFlag(WHOLE_LINE_SCREEN_UNVAILD);

	funRet = wls_SetWLScreenVaildFlag(TMC_WLS_UNVALID);
	ASSER_ERROR(CI_ERROR == funRet,errorCode,0x80000000u);

	funRet = wls_SetUTFlag(UNKNOWN_TRAIN_EXIST);
	ASSER_ERROR(CI_ERROR == funRet,errorCode,0x40000000u);

	funRet = wls_SetEnterCheckFlag(ENTER_ERROR_FLAG);
	ASSER_ERROR(CI_ERROR == funRet,errorCode,0x20000000u);

	/** 获取免筛建立冗余时间 */
	redunTime = wls_PrepareRedunTime();
	wls_SetRedunTime(0u,redunTime);

	funRet = wls_SetUTACCnt(0u);
	ASSER_ERROR(CI_ERROR == funRet,errorCode,0x10000000u);
	for (cycleAC =0u; cycleAC < MAX_UT_AC_CNT; cycleAC++)
	{
		funRet = wls_SetUTACId(cycleAC,0u);
		ASSERT_BREAK(CI_ERROR == funRet,errorCode,0x08000000u); 
	}

	tmpTrainInfo.controlStatus = OUT_CONTROL_STATUS;
	tmpTrainInfo.headNeedScreen = NEED_SCREEN;
	tmpTrainInfo.tailNeedScreen = NEED_SCREEN;

	for (cycle = 1u; cycle < LINE_MAX_TRAIN; cycle++)
	{
		funRet = wls_SetCurTrainStatusInfo(cycle,&tmpTrainInfo);
		ASSERT_BREAK(CI_ERROR == funRet,errorCode,0x04000000u);

		funRet = wls_SetLastTrainStatusInfo(cycle,&tmpTrainInfo);
		ASSERT_BREAK(CI_ERROR == funRet,errorCode,0x02000000u);
	}

	/** 设置函数返回值 */
	ASSERT_SETRET(0u == errorCode, ret, CI_SUCCESS, CI_ERROR);
	ASSER_DEBUG(0u != errorCode, WLS_LOG_LOC(WLS_LOG_ERROR, "errno:0x%08x info:WLS Init error.\n", errorCode));
	return ret;
}


/**
 * @brief 对外接口：全线免筛处理
 * @param[in] 无
 * @param[out] 无
 * @return 无
 * @note 无
 */
void wls_MainProcess(void)
{
	UINT8 isWLSTiocFlag = CI_ERROR;
	UINT8 isfunSwitch = CI_ERROR;
	UINT8 tmcCommStatus = CI_ERROR;

	/** 判断本OC是否为具有免筛属性的TIOC */
	isWLSTiocFlag = wls_PrepareisWLSTioc();
	isfunSwitch = wls_PrepareWLSFunSwitch();

	if ((CI_ERROR == isWLSTiocFlag) || (CI_ERROR == isfunSwitch))
	{
		/** 非具有免筛属性TIOC或者功能开关未打开，不进行处理 */
	}
	else
	{
		tmcCommStatus = wls_PrepareCommStatusWithTMC();

		if (CI_ERROR == tmcCommStatus)
		{
			wls_ClearWLSInfoFromTMC();
		}
		else
		{
			/** 无需处理 */
		}

		/** 刷新免筛序列号 */
		wls_JudgeWLScreenSeqChange();

		/** 判断是否具备免筛 */
		wls_JudgeWLScreenPermit();
	}
}

/**
 * @brief 对外接口：跟随全线免筛模块数据
 * @param[out] UINT8 *pDataBuff 跟随数据的存储地址指针
 * @param[in] UINT32 curIndex 跟随数据的索引地址
 * @return 跟随数据的长度
 * @note 无
 */
UINT32 wls_GetTransferData(OUT UINT8 *pDataBuff,UINT32 curIndex)
{
	/*- 局部变量定义 */
	UINT32 ret = curIndex;
	UINT32 errorCode = 0u;
	UINT32 copyIndex = curIndex;
	const WLSreenInfoStruct *pTemp = NULL;

	/** 入口参数校验*/
	ASSERT_RET_VALUE(NULL == pDataBuff,ret,0x80000000u);

	/** 获取全线免筛信息指针 */
	pTemp = wls_GetWholeLineScreeInfo(); /*不会返回NULL*/

	 /* 设置模块开始标识 */
	pDataBuff[copyIndex++] = (UINT8)'W';
	pDataBuff[copyIndex++] = (UINT8)'L';
	pDataBuff[copyIndex++] = (UINT8)'S';

	/** 跟随全线免筛信息 */
	(void)CommonMemCpy((void*)&pDataBuff[copyIndex], (UINT32)sizeof(WLSreenInfoStruct), (const void *)pTemp, (UINT32)sizeof(WLSreenInfoStruct));
	copyIndex += (UINT32)sizeof(WLSreenInfoStruct);

	/** 处理正确*/
	ret = copyIndex;

	/** 函数返回 */
	return ret;
}


/**
 * @brief 对外接口：拷贝全线免筛模块数据
 * @param[in] const UINT8 *pDatabuff 跟随数据的存储地址指针
 * @param[in] UINT32 curIndex 跟随数据的索引地址
 * @param[in] UINT32 len 跟随数据的长度
 * @return 截取数据索引
 * @note 
 */
UINT32 wls_SetTransferData(IN const UINT8 *pDatabuff,UINT32 curIndex,UINT32 len)
{
	UINT32 ret = curIndex;
	UINT32 errorCode = 0u;
	UINT32 setIndex = curIndex;
	UINT8 modelFlag[3u] = {0u};
	UINT8 funRtn = CI_ERROR;
	WLSreenInfoStruct tmpWLScreenInfo = {0u};   /* 此处需要注意，当以后改WLSreenInfoStruct时，需要考虑对栈区的影响 */

	/** 入口参数判断 */
	ASSERT_RET_VALUE(NULL == pDatabuff,ret,0x80000000u);
	ASSERT_RET_VALUE(curIndex >= len,ret,0x40000000u);

	/** 获取模块开始标识 */
	modelFlag[0u] = pDatabuff[setIndex++];
	modelFlag[1u] = pDatabuff[setIndex++];
	modelFlag[2u] = pDatabuff[setIndex++];

	/** 判断跟随数据是否正确 */
	if (((UINT8)'W' != modelFlag[0u]) || ((UINT8)'L' != modelFlag[1u]) || ((UINT8)'S' != modelFlag[2u]))
	{	
		errorCode = errorCode + 0x20000000u;
		WLS_LOG_LOC(WLS_LOG_ERROR,"errno:0x%08x info:set WLS TransferData by head:%c%c%C error.",errorCode,modelFlag[0u],modelFlag[1u],modelFlag[2u]);
	}
	else
	{
		/** 拷贝全线免筛信息 */
		(void)CommonMemCpy(&tmpWLScreenInfo, (UINT32)sizeof(WLSreenInfoStruct),&pDatabuff[setIndex], (UINT32)sizeof(WLSreenInfoStruct));
		setIndex += (UINT32)sizeof(WLSreenInfoStruct);

		/** 设置跟随信息 */
		funRtn = wls_SetWholeLineScreeInfo(&tmpWLScreenInfo);
		ASSER_ERROR(CI_ERROR == funRtn,errorCode,0x20000000u);

		/** 设置返回值 */
		ASSERT_SETRET((0u == errorCode) && (setIndex <= len), ret, setIndex, ret);
		ASSER_DEBUG(0u != errorCode, WLS_LOG_LOC(WLS_LOG_ERROR, "errno:0x%08x info:WLS Set dataIndex%d.dataLen:%d.\n", errorCode, setIndex, len));
	}

	return ret;
}


/**
 * @brief 对外接口：准备对外发送的信息
 * @param[in] 无
 * @param[out] WLScreenReportStruct *pOutInfo
 * @return CI_ERROR 处理错误；CI_SUCCESS 处理成功
 * @note 无
 */
UINT8 wls_PrepareWLSInfoToTMC(OUT WLScreenReportStruct *pOutInfo)
{
	UINT8 ret = CI_ERROR;
	UINT32 errorCode = 0u;
	UINT16 cycle = 0u;
	const WLSreenInfoStruct* pWLScreenInfo = NULL;
	const WLTrainStatusInfoStruct *pTrainInfo = NULL;

	/** 入口参数校验 */
	ASSERT_RET_VALUE(NULL == pOutInfo,ret,0x80000000u);

	/** 获取全线免筛信息 */
	pWLScreenInfo = wls_GetWholeLineScreeInfo();/*不会返回NULL*/

	pOutInfo->sendSeq = pWLScreenInfo->sendSeq;
	pOutInfo->UTFlag = pWLScreenInfo->UTFlag;
	pOutInfo->enterCheckFlag = pWLScreenInfo->enterCheckFlag;

	pOutInfo->controlTrainCnt = 0u;
	pOutInfo->offlineTrainCnt = 0u;

	for (cycle = 1u; cycle < LINE_MAX_TRAIN; cycle++)
	{
		pTrainInfo = wls_GetCurTrainStatusInfo(cycle);
		ASSERT_BREAK(NULL == pTrainInfo, errorCode, 0x20000000u);

		if ((IN_CONTROL_STATUS == pTrainInfo->controlStatus) && (pOutInfo->controlTrainCnt < TRAIN_SUM_MAX_IN_OC))
		{
			pOutInfo->controlTrainID[pOutInfo->controlTrainCnt] = cycle;
			pOutInfo->controlTrainCnt++;
		}
		else if ((OFFLINE_CONFIRM_STATUS == pTrainInfo->controlStatus) && (pOutInfo->controlTrainCnt < TRAIN_SUM_MAX_IN_OC))
		{
			pOutInfo->offlineTrainID[pOutInfo->offlineTrainCnt] = cycle;
			pOutInfo->offlineTrainCnt++;
		}
		else
		{
			/** 无需处理 */
		}
	}


	/** 设置返回值 */
	ASSERT_SETRET(0u == errorCode, ret, CI_SUCCESS, CI_ERROR);
	ASSER_DEBUG(0u != errorCode, WLS_LOG_LOC(WLS_LOG_ERROR, "errno:0x%08x info:Prepare Train%d Info To TMC error.\n", errorCode, cycle));

	return ret;
}


/**
 * @brief 对外接口：准备对外发送的信息
 * @param[in] const WLScreenReciveStruct *pInInfo
 * @param[out] 无
 * @return 无
 * @note 无
 */
void wls_RefreshWLSInfoFromTMC(IN const WLScreenReciveStruct *pInInfo)
{
	UINT32 errorCode = 0u;
	UINT8 funRtn = CI_ERROR;
	UINT16 cycle = 0u;
	UINT16 cycleTrain = 0u;
	const WLTrainStatusInfoStruct* pTrainInfo = NULL;

	/** 入口参数校验 */
	if (NULL == pInInfo)
	{
		wls_ClearWLSInfoFromTMC();
	}
	else
	{
		/** 设置接收到的序列号 */
		wls_SetRecvSeq(pInInfo->recvSeq);

		/** 设置全线免筛标志 */
		funRtn = wls_SetWLScreenVaildFlag(pInInfo->WLScreenVaildFlag);
		ASSER_ERROR(CI_ERROR == funRtn,errorCode,0x40000000u);

		for (cycle = 1u; cycle < LINE_MAX_TRAIN; cycle++)
		{
			pTrainInfo = wls_GetCurTrainStatusInfo(cycle);

			if ((NULL != pTrainInfo) && (OFFLINE_CONFIRM_STATUS == pTrainInfo->controlStatus))
			{
				/** 如果下线车不在全线受控车范围内，则设置列车状态为不处在控制状态 */
				for (cycleTrain = 0u; cycleTrain < pInInfo->WLTrainCnt;cycleTrain++)
				{
					if (cycle == pInInfo->WLTrainID[cycleTrain])
					{
						break;
					}
				}

				if (cycleTrain == pInInfo->WLTrainCnt)
				{
					wls_SetTrainControlStatus(cycle,OUT_CONTROL_STATUS,NEED_SCREEN,NEED_SCREEN);
				}
				else
				{
					/** 无需处理 */
				}
			}
		}
	}
}

/**
 * @brief 对外接口：清除从TMC接收到信息
 * @param[in] 无
 * @param[out] 无
 * @return 无
 * @note 无
 */
void wls_ClearWLSInfoFromTMC(void)
{
	UINT8 funRet = CI_ERROR;
	UINT32 errorCode = 0u;

	wls_SetRecvSeq(0u);
	wls_SetWLScreenProcessFlag(WHOLE_LINE_SCREEN_UNVAILD);

	funRet = wls_SetWLScreenVaildFlag(TMC_WLS_UNVALID);
	ASSER_ERROR(CI_ERROR == funRet,errorCode,0x80000000u);

	ASSER_DEBUG(0u != errorCode, WLS_LOG_LOC(WLS_LOG_ERROR, "errno:0x%08x info:Clear WLS Info From TMC error.\n", errorCode));
}

/**
 * @brief 对外接口:设置列车的控制状态
 * @param[in] UINT16 trainID 列车ID
 * @param[in] UINT8 ControlStatus 列车控制状态
 * @param[in] UINT8 headFlag 前方隐藏车标志
 * @param[in] UINT8 tailFlag 后方隐藏车标志
 * @param[out] 无
 * @return 无
 * @note 
 */
void wls_SetTrainControlStatus(UINT16 trainID,UINT8 ControlStatus,UINT8 headFlag, UINT8 tailFlag)
{
	UINT8 funRtn = CI_ERROR;
	WLTrainStatusInfoStruct temp = {0u};
	
	temp.controlStatus = ControlStatus;
	temp.headNeedScreen = headFlag;
	temp.tailNeedScreen = tailFlag;
	funRtn = wls_SetCurTrainStatusInfo(trainID,&temp);

	if (CI_ERROR == funRtn)
	{
		WLS_LOG_LOC(WLS_LOG_ERROR, "info:Set Train%d Control Status error.\n", trainID);
	}
	else
	{
		/** 不处理 */
	}
}

/**
 * @brief 对外接口：获取列车的控制状态
 * @param[in] UINT16 trainID 列车ID
 * @param[out] 无
 * @return OUT_CONTROL_STATUS 不处在控制状态的车；IN_CONTROL_STATUS 处在控制状态的车；OFFLINE_CONFIRM_STATUS 处在下线待确认的车
 * @note 状态为下线为安全侧
 */
UINT8 wls_GetTrainControlStatus(UINT16 trainID)
{
	UINT8 ret = OFFLINE_CONFIRM_STATUS;
	const WLTrainStatusInfoStruct* pInfo = NULL;

	pInfo = wls_GetCurTrainStatusInfo(trainID);

	if (NULL != pInfo)
	{
		ret = pInfo->controlStatus;
	}
	else
	{
		/* 不处理 */
	}
	return ret;
}

/**
 * @brief 对外接口：获取免筛可执行标志
 * @param[in] 
 * @param[out]
 * @return WHOLE_LINE_SCREEN_VAILD 全线免筛允许；WHOLE_LINE_SCREEN_UNVAILD 全线免筛不允许
 * @note 
 */
UINT8 wls_GetWLScreenPermitFlag(void)
{
	return wls_GetWLScreenProcessFlag();
}

