#include "vst_work_main.h"
#include "vsm_thread.h"
#include "logic.h"
#include "base.h"
#include "vs_thread.h"
#include "cprocess_laserpowercali.h"
#include "cprocess_locate.h"
#include "cprocess_kerf.h"
#include "cprocess_laserkerf.h"
#include "cprocess_halfcutkerf.h"
int VST_Work_Main::m_iCurSide=-1;
int VST_Work_Main::m_iCurLocateIndex=-1;
VST_Work_Main::VST_Work_Main(int iID, const QString &sName,
                             VSM_Thread *pParent, VS_Thread *pPreState,
                             VS_Thread *pNextState)
    :VST_Work_Base(iID,sName,pParent,pPreState,pNextState)
{

}

void VST_Work_Main::do_Msg(const V_Msg &msg)
{

    if(msg.m_iID==VarMsg_StateExit_ID)
    {
        int iSize=msg.m_vlInput.size();
        if(iSize>1)
        {
            int iStateID=msg.m_vlInput[0].toInt();
            if(iStateID==VarState_Locate_Single_ID)
            {
                int iLocatePos=msg.m_vlInput[1].toInt();
                if(iLocatePos==m_iCurLocateIndex)
                {
                    pushfront_Msg(VarMsg_StateExit_ID,
                                  msg.m_sName,
                                  QVariantList()<<msg.m_vlInput[0].toInt());
                    return;
                }
            }
            else
            {
                int iSide=msg.m_vlInput[1].toInt();
                if(iSide==m_iCurSide)
                {
                    pushfront_Msg(VarMsg_StateExit_ID,
                                  msg.m_sName,
                                  QVariantList()<<msg.m_vlInput[0].toInt());
                    return;
                }
            }
        }
    }

    if (msg.m_iID == VarMsg_PowerCheck_ALL_ID) {
		if (!m_pNextState) {
			m_pNextState = new VST_Work_Main(VarState_PowerCheck_ID,
											 QObject::trUtf8("Power Check"),
											 m_pParent, this, 0);
			
            std::set<CPowerIndex> mapPowerIndex;
            bool bReport = msg.m_vlInput[0].toBool();
            int sideCount = msg.m_vlInput[1].toInt();
            int sideIndexStart = 2;
            if (msg.m_vlInput.size() < sideCount + 1) {
                MQT_THROW_CODESTR(ALARM_POWERCALI_PARAMETER, QObject::trUtf8("PowerCheck Parameter Error"));
            }

			((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
				pushback_Msg(VarMsg_Driver_ID,
					QObject::trUtf8("Before Check Power"),
					QVariantList() << POWERMETERDRIVER
					<< CPowerMeterDriver_lp::kPowerMeterCheck);

			std::list<SINGLECUTPARAM> lstPowerPara;
            for (int i = sideIndexStart; i < sideCount+sideIndexStart; i++) {
                int iSideId = msg.m_vlInput[i].toInt();
                CProductSide* pProductSide = GET_CHDIRECT(iSideId, CProductSide);
                Q_ASSERT(pProductSide);
                QMutexLocker locker(&pProductSide->m_vCutParam.mutex);
                int iSizeParam = pProductSide->m_vCutParam.size();
                Q_ASSERT(iSizeParam > 0);

                for (int i = 0; i < iSizeParam; i++) {
                    //
                    SINGLECUTPARAM Param = pProductSide->m_vCutParam[i];
                    CPowerIndex pPowerIndex(Param.iLaserFreq, Param.iLaserEpulse, Param.dBeamWidth * 1000);
                    if (mapPowerIndex.end() != mapPowerIndex.find(pPowerIndex)) {
                        continue;
                    }

                    mapPowerIndex.insert(pPowerIndex);
					lstPowerPara.emplace_back(Param);
                    
                }
            }

			lstPowerPara.sort([&](const SINGLECUTPARAM& first, const SINGLECUTPARAM& second) {
				return first.dLaserPower < second.dLaserPower;
			});

			for (auto& Param : lstPowerPara) {
				m_gSystem.AddProductInfo(PROCESS_LEVELING, QString("CheckPower:Freq:%1 Epulse:%2 BeamWidth:%3 Power:%4").arg(Param.iLaserFreq).arg(Param.iLaserEpulse).arg(Param.dBeamWidth).arg(Param.dLaserPower));
				MqDebug() << QString("CheckPower:Freq:%1 Epulse:%2 BeamWidth:%3 Power:%4").arg(Param.iLaserFreq).arg(Param.iLaserEpulse).arg(Param.dBeamWidth).arg(Param.dLaserPower);

				int processId = PROCESS_POWERCALI_L_NARROW;
				if (Param.laserpathID == LASERPATH_D_NARROW)
				{
					processId = PROCESS_POWERCALI_D_NARROW;
				}
				else if (Param.laserpathID == LASERPATH_S_NARROW)
				{
					processId = PROCESS_POWERCALI_S_NARROW;
				}
				else if (Param.laserpathID == LASERPATH_D_WIDE)
				{
					processId = PROCESS_POWERCALI_D_WIDE;
				}
				((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
					pushback_Msg(VarMsg_PowerCheck_ID,
						QObject::trUtf8("Power Check"), QVariantList() << processId
						<< Param.iLaserFreq << Param.iLaserEpulse
						<< Param.dBeamWidth << Param.dLaserPower << bReport); //频率和功率
			}

			((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
				pushback_Msg(VarMsg_Driver_ID,
					QObject::trUtf8("After Check Power"),
					QVariantList() << POWERMETERDRIVER
					<< CPowerMeterDriver_lp::kReportCheckResult << bReport);

			((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
		}
		m_pParent->SetState(m_pNextState);
    }
	else if(msg.m_iID == VarMsg_PowerCheck_ID){
        //功率复检
		if(!m_pNextState)
		{
			m_pNextState= new VST_Work_Main(VarState_PowerCheck_ID,
				QObject::trUtf8("Power Check"),m_pParent, this,0);

			//传递检查功率数据
			((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
				pushback_Msg(VarMsg_Process_ID,
				QObject::trUtf8("Check Power"),
				QVariantList()<< msg.m_vlInput[0].toInt()
				<<CProcess_LaserPowerCali::CHECKPOWER<<
				msg.m_vlInput[1].toInt()<< msg.m_vlInput[2].toInt() <<msg.m_vlInput[3].toDouble()<< msg.m_vlInput[4].toDouble() << msg.m_vlInput[5].toBool());

			((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
		}
		m_pParent->SetState(m_pNextState);
	}
    ////////////////边缘定位//////////////////
    else if(msg.m_iID==VarMsg_Locate_Process_ID)
    {
        m_iCurSide=-1;
        m_iCurLocateIndex=-1;
        if(!m_pNextState)
        {
            CProcess_Locate* pLocate=(CProcess_Locate*)m_pParent->FindProcess(PROCESS_LOCATE);

            m_pNextState= new VST_Work_Main(VarState_Locate_Process_ID,
                                            QObject::trUtf8("Locate Process"),
                                            m_pParent,
                                            this,0);
            int iCount=pLocate->m_LocateVector.size();
            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Locate_Process_Before_ID,
                                 QObject::trUtf8("Locate Before Sig"));

            if (!m_gSystem.m_bSimulatorLocation) {
                //执行多次定位操作
                for (int i = 0; i < iCount; i++) {
                    ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                        pushback_Msg(VarMsg_Locate_Single_ID,
                                     QObject::trUtf8("Locate Single"),
                                     QVariantList() << i);

                }
            }
            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Locate_Process_After_ID,
                                 QObject::trUtf8("Locate After Sig"));
            ((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
        }
        m_pParent->SetState(m_pNextState);
		m_gSystem.AddProductInfo(PROCESS_LOCATE, QString("Start Locate at %1").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz")));
    }
    else if(msg.m_iID==VarMsg_Locate_Process_Before_ID)
    {
        CProcess_Locate* pLocate=GET_PROCESS(PROCESS_LOCATE,
                                             SM_MAIN,
                                             CProcess_Locate);
        pLocate->CalcuLocateVector();
        m_gSystem.ChangeSide(-1);
    }
    else if(msg.m_iID==VarMsg_Locate_Single_ID)
    {
        if(!m_pNextState)
        {
            CProcess_Locate* pLocate=(CProcess_Locate*)m_pParent->FindProcess(PROCESS_LOCATE);

            m_pNextState= new VST_Work_Main(VarState_Locate_Single_ID,
                                            QObject::trUtf8("Locate Single"),
                                            m_pParent,
                                            this,0);
            int iIndex= msg.m_vlInput[0].toInt();
            ((VST_Work_Main*)m_pNextState)->m_iCurLocateIndex = iIndex;
            int iSearchCount=pLocate->m_Variants.
                    get_VData(Var_Process_Locate_SearchCount)->toInt();
            for(int i=0;i<iSearchCount;i++)
            {
                ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                        pushback_Msg(VarMsg_Process_ID,
                                     QObject::trUtf8("Move Single"),
                                     QVariantList()<<PROCESS_LOCATE
                                     <<CProcess_Locate::MOVEPOS
                                     <<iIndex<<i);
                ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                        pushback_Msg(VarMsg_Locate_Search_Single_ID,
                                     QObject::trUtf8("Search Single"),
                                     QVariantList()<<iIndex);
            }
            ((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
        }
        m_pParent->SetState(m_pNextState);
    }
    else if(msg.m_iID==VarMsg_Locate_Search_Single_ID)
    {
        CProcess_Locate* pLocate=
                (CProcess_Locate*)m_pParent->FindProcess(PROCESS_LOCATE);
        int iSearchIndex=msg.m_vlInput[0].toInt();
        if(pLocate->SearchPos(iSearchIndex,false))
        {
            pushfront_Msg(VarMsg_StateExit_ID,
                          QObject::trUtf8("Locate Pos %1 Success")
                          .arg(iSearchIndex+1),
                          QVariantList()<<m_iID<<iSearchIndex);
        }
    }
    else if(msg.m_iID==VarMsg_Locate_Process_After_ID)
    {
        CProcess_Locate* pLocate=GET_PROCESS(PROCESS_LOCATE,
                                             SM_MAIN,
                                             CProcess_Locate);

        if (m_gSystem.m_bSimulatorLocation) {
            pLocate->FitCellSimulator();
        } else {
            pLocate->FitCell();
        }

		m_gSystem.AddProductInfo(PROCESS_LOCATE, QString("Finish Locate at %2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz")));
    }
    ////////////////边缘定位 结束//////////////
    ////////////////调平//////////////////
	//先用低倍初调一次，再用高倍精调
    /// A B面调平
    if(msg.m_iID==VarMsg_Align_Process_ID)
    {
        if(!m_pNextState)
        {
            m_pNextState= new VST_Work_Main(VarState_Align_Process_ID,
                                            QObject::trUtf8("Locate Process"),
                                            m_pParent,
                                            this,0);
            int iCurSide= msg.m_vlInput[0].toInt();
            ((VST_Work_Main*)m_pNextState)->m_iCurSide=iCurSide;

			m_gSystem.AddProductInfo(PROCESS_LOCATE, QString("Start Align %1 at %2").arg(iCurSide==SIDE_A?"CH1":"CH2")
				.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz")));

            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Align_Process_Before_ID,
                                 QObject::trUtf8("Align Before Sig"),
                                 QVariantList()<<iCurSide);

            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Align_Rotate_ID,
                                 QObject::trUtf8("Align Rotate"),
                                 QVariantList()<<iCurSide);
            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Main_Align_Near_ID,
                                 QObject::trUtf8("Align Near"),
                                 QVariantList()<<iCurSide);
            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Align_Far_ID,
                                 QObject::trUtf8("Align Far"),
                                 QVariantList()<<iCurSide);
            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Align_Base_ID,
                                 QObject::trUtf8("Align Base"),
                                 QVariantList()<<iCurSide<<0<<true);

            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Align_Process_After_ID,
                                 QObject::trUtf8("Align After Sig"),
                                 QVariantList()<<iCurSide);

			CProductSide* pSide=GET_CHDIRECT(iCurSide,CProductSide);   
			Q_ASSERT(pSide);
			double dStep=pSide->m_Variants.get_VData(Var_ProductSide_SideStep)->toDouble();

			CMProduct* product=GET_CHDIRECT(PRODUCT,CMProduct);
			Q_ASSERT(product);
			double dWaferDiameter = product->m_Variants.get_VData(Var_Product_Diameter_ID)->toDouble();
			int lineSize = dWaferDiameter/dStep+0.5;

			CProcess_Level* pLevel=GET_PROCESS(PROCESS_LEVELING,
				SM_MAIN,CProcess_Level);
			Q_ASSERT(pLevel);
			bool bAlignCheck = pLevel->m_Variants.get_VData(Var_Process_Enable_Align_Check)->toInt()==1;
			if(bAlignCheck){
				((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
					pushback_Msg(VarMsg_Align_Check_ID,
					QObject::trUtf8("Align Check %1").arg(iCurSide==SIDE_A?"CH1":"CH2"),
					QVariantList()<<iCurSide);
			}

			//对划片道进行定位补偿
			int firstLine = 0;
			int stepLine = 0;
			pLevel->getCurSideAlignParam(iCurSide, firstLine, stepLine);
			//如果不等于0，则要进行补偿
			if(firstLine>0)
			{
				//开始和结束时，都要去掉边缘的线，使最后的检测点不能在边缘
				//所以最后要减掉firstLine
				for(int i=firstLine-1;i<=lineSize-firstLine;)
				{
					((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
						pushback_Msg(VarMsg_Process_ID,
						QObject::trUtf8("Calcu Line Align Pos Sig"),
						QVariantList()<<PROCESS_LEVELING
						<<CProcess_Level::CALCU_PT_BY_LINE<<iCurSide<<i);

					((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
						pushback_Msg(VarMsg_Align_Base_ID,
						QObject::trUtf8("Align Base"),
						QVariantList()<<iCurSide<<i<<false);

					//如果没有频率，则相当于只在第一次进行一下
					if(stepLine == 0)
						break;

					i+=stepLine;
				}
			}
			
            ((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
        }
        m_pParent->SetState(m_pNextState);

    }
    else if(msg.m_iID==VarMsg_Align_Process_Before_ID)
    {
        CProcess_Level* pAlign=(CProcess_Level*)m_pParent->FindProcess(PROCESS_LEVELING);
        int iSideID=msg.m_vlInput[0].toInt();
        pAlign->ChangeToLevelSide(iSideID);
        m_iCurSide=iSideID;

    }
    else if(msg.m_iID==VarMsg_Align_Process_After_ID)
    {
        CProcess_Level* pAlign=(CProcess_Level*)m_pParent->FindProcess(PROCESS_LEVELING);
        int iSideID=msg.m_vlInput[0].toInt();
        pAlign->CalcuPtByCell(iSideID);

		m_gSystem.AddProductInfo(PROCESS_LOCATE, QString("Finish Align %1 at %2").arg(iSideID==SIDE_A?"CH1":"CH2")
			.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz")));
    }
    else if(VarMsg_Align_Search_ID==msg.m_iID)
    {
        CProcess_Level* pAlign=(CProcess_Level*)m_pParent->FindProcess(PROCESS_LEVELING);
        int iSideID=msg.m_vlInput[0].toInt();
        int iCamID=msg.m_vlInput[1].toInt();
        int ptType=msg.m_vlInput[2].toInt();
        switch(ptType)
        {
        case CProcess_Level::TYPE_PTROTATE:
            pAlign->SearchRotatePt(iSideID,iCamID);
            if(pAlign->m_AlignPtRotate.bHasMatch)
            {
                double dAngleThres= pAlign->m_Variants.
                        get_VData(Var_Process_Level_AngleThres)->toDouble();
				//旋转调平角度可以大一点
                if(fabs(pAlign->m_AlignPtRotate.dAngle)<dAngleThres)
                {
                    pushfront_Msg(VarMsg_StateExit_ID,
                                  QObject::trUtf8("Exit Rotate Alignment"),
                                  QVariantList()<<VarState_Align_Rotate_ID<<iSideID);
                    return;

                }
                else
                {
					//没找到，旋转一个角度，退出当前流程进行下一个VarState_Align_R_MoveSearch_ID流程
                    pAlign->Turn_Angle(iSideID,ptType);
                    pushfront_Msg(VarMsg_StateExit_ID,
                                  QObject::trUtf8("Exit Rotate Search"),
                                  QVariantList()<<VarState_Align_R_MoveSearch_ID<<iSideID);
                }
            }
            break;
        case CProcess_Level::TYPE_PT1:
        {
            pAlign->SearchAlignPt(iSideID,iCamID,ptType);
            if(pAlign->m_AlignPt1.bHasMatch)
            {
                pushfront_Msg(VarMsg_StateExit_ID,
                              QObject::trUtf8("Exit Pt1 Search"),
                              QVariantList()<<VarState_Align_Pt1_MoveSearch_ID<<iSideID);
            }

            break;
        }
        case CProcess_Level::TYPE_PTMID:
        {
            double dOffset= pAlign->SearchAlignPt(iSideID,iCamID,ptType);
            double dOffsetThres=pAlign->m_Variants.get_VData(Var_Process_Level_MidOffsetThres)
                    ->toDouble();
            if(pAlign->m_AlignPtMid.bHasMatch)
            {
				//满足拉平阈值后，就停止
                if(fabs(dOffset)<dOffsetThres)
                {
                    pushfront_Msg(VarMsg_StateExit_ID,
                                  QObject::trUtf8("Exit Near Alignment"),
                                  QVariantList()<<VarState_Align_Near_ID<<iSideID);
                    return;

                }
                else
                {
					//调整角度后，再找点1和中点拉平
                    pAlign->Turn_Angle(iSideID,ptType);
                    pushfront_Msg(VarMsg_StateExit_ID,
                                  QObject::trUtf8("Exit PtMid Search"),
                                  QVariantList()<<VarState_Align_PtMid_MoveSearch_ID<<iSideID);

                }
            }
            break;
        }
        case CProcess_Level::TYPE_PT2:
        {
            double dOffset= pAlign->SearchAlignPt(iSideID,iCamID,ptType);
            double dOffsetThres=pAlign->m_Variants.get_VData(Var_Process_Level_OffsetThres)
                    ->toDouble();
            if(pAlign->m_AlignPt2.bHasMatch)
            {
                if(fabs(dOffset)<dOffsetThres)
                {
                    pushfront_Msg(VarMsg_StateExit_ID,
                                  QObject::trUtf8("Exit Far Alignment"),
                                  QVariantList()<<VarState_Align_Far_ID<<iSideID);
                    return;

                }
                else
                {
                    pAlign->Turn_Angle(iSideID,ptType);
                    pushfront_Msg(VarMsg_StateExit_ID,
                                  QObject::trUtf8("Exit Pt2 Search"),
                                  QVariantList()<<VarState_Align_Pt2_MoveSearch_ID<<iSideID);

                }
            }
            break;
        }

        case CProcess_Level::TYPE_PTBASE:
        {
			//HACK:
            //int iLineID=msg.m_vlInput[3].toInt();
			int iLineID=msg.m_vlInput[3].toInt();
            pAlign->SearchBasePt(iSideID, iCamID, iLineID);
            if(pAlign->m_AlignPtBase.bHasMatch)
            {
                pushfront_Msg(VarMsg_StateExit_ID,
                              QObject::trUtf8("Exit Align Base Search"),
                              QVariantList()<<VarState_Align_PtBase_MoveSearch_ID<<iSideID);
                return;
            }
            break;
        }

        }
    }
    else if(VarMsg_Align_SearchFail_ID==msg.m_iID)
    {
        CProcess_Level* pLevel=GET_PROCESS(PROCESS_LEVELING,
                                           SM_MAIN,
                                           CProcess_Level);
        int iSideID=msg.m_vlInput[0].toInt();
        int iCamID=msg.m_vlInput[1].toInt();
        int ptType=msg.m_vlInput[2].toInt();
        pLevel->MovePt(iSideID,iCamID,ptType,false,0,0);
        switch(ptType)
        {
        case CProcess_Level::TYPE_PTROTATE:
			MQT_THROW_CODESTR(ALARM_MAIN_SERACHPT_SearchRotateFailed, QObject::trUtf8("Rotate Search Failed"));
            break;
        case CProcess_Level::TYPE_PT1:
            MQT_THROW_CODESTR(ALARM_MAIN_SERACHPT_SearchPt1Failed, QObject::trUtf8("Point1 Search Failed"));
            break;
        case CProcess_Level::TYPE_PTMID:
            MQT_THROW_CODESTR(ALARM_MAIN_SERACHPT_SearchMIDFailed, QObject::trUtf8("Middle Point Search Failed"));
            break;
        case CProcess_Level::TYPE_PT2:
            MQT_THROW_CODESTR(ALARM_MAIN_SERACHPT_SearchPt2Failed, QObject::trUtf8("Point2 Point Search Failed"));
            break;
        case CProcess_Level::TYPE_PTBASE:
			bool bAlign = msg.m_vlInput[3].toBool();
			if(bAlign){
				MQT_THROW_CODESTR(ALARM_MAIN_SERACHPT_SearchBaseFailed, (QObject::tr("Align err.\n") + QObject::trUtf8("Base Point Search Failed")));
			}
			else{
				MQT_THROW_CODESTR(ALARM_MAIN_SERACHPT_SearchBaseAdjustFailed, QObject::trUtf8("Base Point Search Failed"));
			}
            break;
        }
    }
    else if(VarMsg_Align_AlignFail_ID==msg.m_iID)
    {
        CProcess_Level* pLevel=GET_PROCESS(PROCESS_LEVELING,
                                           SM_MAIN,
                                           CProcess_Level);
        int iSideID=msg.m_vlInput[0].toInt();
        int iCamID=msg.m_vlInput[1].toInt();
        int ptType=msg.m_vlInput[2].toInt();
        pLevel->MovePt(iSideID,iCamID,ptType,false,0,0);
        switch(ptType)
        {
        case CProcess_Level::TYPE_PTROTATE:
            MQT_THROW_CODESTR(ALARM_MAIN_ALIGNPT_AlignSearchFailed, QObject::trUtf8("Rotate Align Failed"));
            break;
        case CProcess_Level::TYPE_PTMID:
            MQT_THROW_CODESTR(ALARM_MAIN_ALIGNPT_AlignMidFailed, QObject::trUtf8("Middle Point Align Failed"));
            break;
        case CProcess_Level::TYPE_PT2:
            MQT_THROW_CODESTR(ALARM_MAIN_ALIGNPT_AlignPt2Failed, QObject::trUtf8("Point2 Point Align Failed"));
            break;
        }
    }
    //单点调平
    //HACK:调平基准点
    if(msg.m_iID==VarMsg_Align_Rotate_ID)
    {
        int iSideID=msg.m_vlInput[0].toInt();
        CProcess_Level* pAlign=(CProcess_Level*)m_pParent->FindProcess(PROCESS_LEVELING);
        int iMaxAlignCount=pAlign->m_Variants.
                get_VData(Var_Process_Level_MaxLevelCount)
                ->toInt();
        if(!m_pNextState)
        {
            m_pNextState= new VST_Work_Main(VarState_Align_Rotate_ID,
                                            QObject::trUtf8("Align Rotate"),
                                            m_pParent, this,0);
            for(int i=0;i<iMaxAlignCount;i++)
            {
                ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                        pushback_Msg(VarMsg_Align_R_MoveSearch_ID,
                                     QObject::trUtf8("Search Rotate"),
                                     QVariantList()<<iSideID<<i);

            }
            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Align_AlignFail_ID,
                                 QObject::trUtf8("Align Rotate Failed Sig"),
                                 QVariantList()<<iSideID
                                 <<pAlign->m_iLocateCamID
                                 <<CProcess_Level::TYPE_PTROTATE);

            ((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
        }
        m_pParent->SetState(m_pNextState);
    }
    if(msg.m_iID==VarMsg_Align_R_MoveSearch_ID)
    {
        CProcess_Level* pAlign=(CProcess_Level*)m_pParent->FindProcess(PROCESS_LEVELING);

        //HACK:平移搜索基准点，就是找第一个点
        if(!m_pNextState)
        {
            int iSideID=msg.m_vlInput[0].toInt();
            m_pNextState= new VST_Work_Main(VarState_Align_R_MoveSearch_ID,
                                            QObject::trUtf8("Align Rotate Search"),
                                            m_pParent, this,0);
			//使用低倍相机进行旋转调平，根据步长和视野判断
            int iXAdjustCount=pAlign->get_XAdjust_count(iSideID,pAlign->m_iLocateCamID);
            int iYAdjustCount=pAlign->get_YAdjust_count(iSideID,pAlign->m_iLocateCamID);
            for(int i=0;i<iXAdjustCount;i++)
            {
                for(int j=0;j<iYAdjustCount;j++)
                {
                    ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                            pushback_Msg(VarMsg_Process_ID,
                                         QObject::trUtf8("Move Rotate Pos"),
                                         QVariantList()<<PROCESS_LEVELING
                                         <<CProcess_Level::MOVE_PT
                                         <<msg.m_vlInput[0]<<pAlign->m_iLocateCamID
                                                          <<CProcess_Level::TYPE_PTROTATE<<true<<i<<j);

                    ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                            pushback_Msg(VarMsg_Align_Search_ID,
                                         QObject::trUtf8("Align Cam Search Sig"),
                                         QVariantList()<<iSideID
                                         <<pAlign->m_iLocateCamID
                                         <<CProcess_Level::TYPE_PTROTATE);

                }
            }

			//如果最后都没找到模板，则会进入这个失败消息，提前找到，这个消息就提前被Exit掉了
			//所以不会进入，因为提前响应了VarMsg_StateExit_ID消息
            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Align_SearchFail_ID,
                                 QObject::trUtf8("Align Cam Search Fail Sig"),
                                 QVariantList()<<msg.m_vlInput[0]
                    <<pAlign->m_iLocateCamID
                   <<CProcess_Level::TYPE_PTROTATE );

            ((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
        }
        m_pParent->SetState(m_pNextState);
    }
    //单点调平 结束
    //近点调平
    if(msg.m_iID==VarMsg_Main_Align_Near_ID)
    {
        CProcess_Level* pAlign=(CProcess_Level*)m_pParent->FindProcess(PROCESS_LEVELING);

        int iMaxAlignCount=pAlign->m_Variants.get_VData(Var_Process_Level_MaxLevelCount)
                ->toInt();
        int iSideID=msg.m_vlInput[0].toInt();
        if(!m_pNextState)
        {
            m_pNextState= new VST_Work_Main(VarState_Align_Near_ID,
                                            QObject::trUtf8("Align Near"), m_pParent,
                                            this,0);
            for(int i=0;i<iMaxAlignCount;i++)
            {
                ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                        pushback_Msg(VarMsg_Align_Pt1_MoveSearch_ID,
                                     QObject::trUtf8("Search pt1"),
                                     QVariantList()<<iSideID<<i);

                ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                        pushback_Msg(VarMsg_Align_PtMid_MoveSearch_ID,
                                     QObject::trUtf8("Search ptMid"),
                                     QVariantList()<<iSideID<<i);

            }

            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Align_AlignFail_ID,
                                 QObject::trUtf8("Align PointMid Failed Sig"),
                                 QVariantList()<<iSideID
                                 <<pAlign->m_iMatchCamID<<
                                 CProcess_Level::TYPE_PTMID);

            ((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
        }
        m_pParent->SetState(m_pNextState);
    }
    if(msg.m_iID==VarMsg_Align_Pt1_MoveSearch_ID||
            msg.m_iID==VarMsg_Align_PtMid_MoveSearch_ID||
            msg.m_iID==VarMsg_Align_Pt2_MoveSearch_ID||
            msg.m_iID==VarMsg_Align_PtBase_MoveSearch_ID)
    {
        int iPtType=CProcess_Level::TYPE_PT1;
        int iState=VarState_Align_Pt1_MoveSearch_ID;
        QString strStateName=QObject::trUtf8("Pt1 Search");
        QString strMoveSig=QObject::trUtf8("Pt1 Move Sig");
        QString strSearchSig=QObject::trUtf8("Pt1 Search Sig");
        QString strFailSig=QObject::trUtf8("Pt1 Search Fail Sig");
        switch(msg.m_iID)
        {
        case VarMsg_Align_PtMid_MoveSearch_ID:
            iPtType=CProcess_Level::TYPE_PTMID;
            iState=VarState_Align_PtMid_MoveSearch_ID;
            strStateName=QObject::trUtf8("PtMid Search");
            strMoveSig=QObject::trUtf8("PtMid Move Sig");
            strSearchSig=QObject::trUtf8("PtMid Search Sig");
            strFailSig=QObject::trUtf8("PtMid Search Fail Sig");
            break;
        case VarMsg_Align_Pt2_MoveSearch_ID:
            iPtType=CProcess_Level::TYPE_PT2;
            iState=VarState_Align_Pt2_MoveSearch_ID;
            strStateName=QObject::trUtf8("Pt2 Search");
            strMoveSig=QObject::trUtf8("Pt2 Move Sig");
            strSearchSig=QObject::trUtf8("Pt2 Search Sig");
            strFailSig=QObject::trUtf8("Pt2 Search Fail Sig");

            break;
        case VarMsg_Align_PtBase_MoveSearch_ID:
            iPtType=CProcess_Level::TYPE_PTBASE;
            iState=VarState_Align_PtBase_MoveSearch_ID;
            strStateName=QObject::trUtf8("PtBase Search");
            strMoveSig=QObject::trUtf8("PtBase Move Sig");
            strSearchSig=QObject::trUtf8("PtBase Search Sig");
            strFailSig=QObject::trUtf8("PtBase Search Fail Sig");
            break;
        }
        CProcess_Level* pAlign=(CProcess_Level*)m_pParent->FindProcess(PROCESS_LEVELING);

        if(!m_pNextState)
        {
            m_pNextState= new VST_Work_Main(iState, strStateName,
                                            m_pParent, this,0);
            int iXAdjustCount=pAlign->m_Variants.get_VData(Var_Process_Level_MaxSearchCount)
                    ->toInt();

            for(int i=0;i<iXAdjustCount;i++)
            {
                ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                        pushback_Msg(VarMsg_Process_ID, strMoveSig,
                                     QVariantList()<<PROCESS_LEVELING
                                     <<CProcess_Level::MOVE_PT
                                     <<msg.m_vlInput[0]<<pAlign->m_iMatchCamID
                                                      <<iPtType<<true<<i<<0);

                ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                        pushback_Msg(VarMsg_Align_Search_ID,strSearchSig,
                                     QVariantList()<<msg.m_vlInput[0]
                        <<pAlign->m_iMatchCamID
                       <<iPtType);
            }
            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Align_SearchFail_ID, strFailSig,
                                 QVariantList()<<msg.m_vlInput[0]
                    <<pAlign->m_iMatchCamID  <<iPtType );

            ((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
        }
        m_pParent->SetState(m_pNextState);
    }
    //近点调平 结束
    //远点调平
    if(msg.m_iID==VarMsg_Align_Far_ID)
    {
        CProcess_Level* pAlign=
                (CProcess_Level*)m_pParent->FindProcess(PROCESS_LEVELING);
        int iMaxAlignCount=pAlign->m_Variants.
                get_VData(Var_Process_Level_MaxLevelCount) ->toInt();

        if(!m_pNextState)
        {
            int iSideID=msg.m_vlInput[0].toInt();
            m_pNextState= new VST_Work_Main(VarState_Align_Far_ID,
                                            QObject::trUtf8("Align Far"),
                                            m_pParent, this,0);
            for(int i=0;i<iMaxAlignCount;i++)
            {
                ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                        pushback_Msg(VarMsg_Align_Pt1_MoveSearch_ID,
                                     QObject::trUtf8("Search pt1"),
                                     QVariantList()<<iSideID<<i);

                ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                        pushback_Msg(VarMsg_Align_Pt2_MoveSearch_ID,
                                     QObject::trUtf8("Search ptMid"),
                                     QVariantList()<<iSideID<<i);

            }

            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Align_AlignFail_ID,
                                 QObject::trUtf8("Align PointFar Failed Sig"),
                                 QVariantList()<<iSideID
                                 <<pAlign->m_iMatchCamID
                                 <<CProcess_Level::TYPE_PT2);


            ((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
        }
        m_pParent->SetState(m_pNextState);

    }
    //远点调平 结束
    //基准设定
    if(msg.m_iID==VarMsg_Align_Base_ID)
    {
        CProcess_Level* pAlign=
                (CProcess_Level*)m_pParent->FindProcess(PROCESS_LEVELING);
        pAlign->m_AlignPtBase.StateReset();
        if(!m_pNextState)
        {
            m_pNextState= new VST_Work_Main(VarState_Align_PtBase_MoveSearch_ID,
                                            QObject::trUtf8("Align Base Search"),
                                            m_pParent, this,0);

            int iXAdjustCount=pAlign->m_Variants.get_VData(Var_Process_Level_MaxSearchCount)
                    ->toInt();
            for(int i=0;i<iXAdjustCount;i++)
            {
                ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                        pushback_Msg(VarMsg_Process_ID,
                                     QObject::trUtf8("Move Base Pos"),
                                     QVariantList()<<PROCESS_LEVELING
                                     <<CProcess_Level::MOVE_PT
                                     <<msg.m_vlInput[0]<<pAlign->m_iMatchCamID
                                                      <<CProcess_Level::TYPE_PTBASE<<true<<i<<0);

                ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                        pushback_Msg(VarMsg_Align_Search_ID,
                                     QObject::trUtf8("Align Cam Search Sig"),
                                     QVariantList()<<msg.m_vlInput[0]
                        <<pAlign->m_iMatchCamID
                       <<CProcess_Level::TYPE_PTBASE
					   <<msg.m_vlInput[1]);
            }

			//TODO:多次进行基准点调平

            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Align_SearchFail_ID,
                                 QObject::trUtf8("Base Cam Search Fail Sig"),
                                 QVariantList()<<msg.m_vlInput[0]
                    <<pAlign->m_iMatchCamID
                   <<CProcess_Level::TYPE_PTBASE<<msg.m_vlInput[2]);

            ((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
        }
        m_pParent->SetState(m_pNextState);
    }
    //基准设定 结束
    ///////////////////调平 结束
    ///////////////////加工
    if(msg.m_iID==VarMsg_Cut_Process_ID)
    {
		//TODO:这里将传递取消切割的线，用于处理异常恢复
        int iSideID=msg.m_vlInput[0].toInt();
        CProductSide* pSide=GET_CHDIRECT(iSideID,CProductSide);
		pSide->WriteRecoveredData();
		pSide->RecordLineData();
        QMutexLocker locker1(&pSide->m_CutLineVector.mutex);
        QMutexLocker locker2(&pSide->m_vCutParam.mutex);
        int isizeLayer=pSide->m_vCutParam.size();		//Layer是第几个PASS的意思
        int isizeLine=pSide->m_CutLineVector.size();
        m_gSystem.ChangeSide(iSideID);
        if(!m_pNextState)
        {
            m_pNextState= new VST_Work_Main(VarState_Cut_Process_ID,
                                            QObject::trUtf8("Cut Single Layer"),
                                            m_pParent,this,0);
            ((VST_Work_Main*)m_pNextState)->m_iCurSide=iSideID;
			//TODO:切割的流程第几层和第几条线的循环需要调整
			//默认从0开始，为-1时则不生效
			////控制自动时切割哪些切割道
			//if(iSideID == SIDE_A){
			//	startLine = m_gSystem.m_iAsideStart;
			//	endLine = m_gSystem.m_iAsideEnd;
			//}else if(iSideID == SIDE_B){
			//	startLine = m_gSystem.m_iBsideStart;
			//	endLine = m_gSystem.m_iBsideEnd;
			//}
			int startLine = msg.m_vlInput[1].toInt(); //从0开始，为-1时则不生效
			int endLine = msg.m_vlInput[2].toInt();	// 从0开始，为-1时则不生效
			Q_ASSERT(msg.m_vlInput.size()==7);
			bool bEnableKerf = msg.m_vlInput[3].toBool();				//这个好像没什么用
			int iTargetLayer = max(0, msg.m_vlInput[4].toInt());		//从1开始 
			int iTargetTimes = max(0, msg.m_vlInput[5].toInt());		//从1开始

			QString info = QString("Cut Process:\tat %6\n\tSIDE:%1 LineStart:%2 LineEnd:%3 Pass:%4 Times:%5")
				.arg(iSideID==SIDE_A?"CH1":"CH2").arg(startLine+1).arg(endLine+1)
				.arg(iTargetLayer+1).arg(iTargetTimes+1)
				.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz"));

			m_gSystem.AddProductInfo(PROCESS_CUT, info);
			LOG_INFO(info.toLocal8Bit().data());
            CProduct* pProduct = GET_CHDIRECT(PRODUCT, CProduct);
            bool_t bLineCycle = pProduct->m_Variants.get_VData(Var_MProduct_CutType_ID)
                ->toUInt() == 0;

            if (bLineCycle)
            {
                //一次把所有线都切割完
                for (int j = 0; j < isizeLine; j++)
                {
                    if (startLine >= 0 && j < startLine)
                    {
                        MqDebug() << "Skip Start Cut Line:" << j + 1;
                        continue;
                    }
                    if (endLine >= 0 && j > endLine)
                    {
                        MqDebug() << "Skip End Cut Line:" << j + 1;
                        continue;
                    }

                    //sizeLayser为通道，即切割的参数
                    for (int i = 0; i < isizeLayer; i++)
                    {
                        //如果是第一条线，并且层数
                        if (j == startLine && i < iTargetLayer)
                        {
                            continue;
                        }

                        AddCalcuPosSig((VST_Work_Main*)m_pNextState, iSideID, j, i);

#ifdef __SIMULATOR__
                        //激光刀痕检测
                        //AddKerfLaserCutSig((VST_Work_Main*)m_pNextState,iSideID,j,i); //切割后定位
#endif // __SIMULATOR__

                    //半切刀痕检测
                        if (i == 0)
                        {
                            //只在第一层时检查刀痕
                            CProcess_Level* pLevel = GET_PROCESS(PROCESS_LEVELING,
                                                                 SM_MAIN, CProcess_Level);
                            bool bAlignCheck = pLevel->m_Variants.get_VData(Var_Process_EnableHalfcut_Check)->toInt() == 1;
                            if (bAlignCheck)
                            {
                                AddHalfKerfSig((VST_Work_Main*)m_pNextState, iSideID, j, i);
                            }
                            else
                            {
                                AddTargetSig((VST_Work_Main*)m_pNextState, iSideID, j, i);
                            }
                        }

                        //切割
                        //第一条线的时候
                        //startLine不启用的时候是传入的0
                        if (j == startLine && iTargetLayer == i)
                        {
                            AddCutSig((VST_Work_Main*)m_pNextState, iSideID, j, i, iTargetTimes);
                        }
                        else
                        {
                            AddCutSig((VST_Work_Main*)m_pNextState, iSideID, j, i, 0);
                        }

                        //切割后Kerf
                        //切割后刀痕检测
                        AddKerfSig((VST_Work_Main*)m_pNextState, iSideID, j, i);
                    }
                }
            }
            else
            {
                //一次切割一个线
                for (int i = 0; i < isizeLayer; i++)
                {
                    for (int j = 0; j < isizeLine; j++)
                    {
                        if (startLine >= 0 && j < startLine)
                        {
                            MqDebug() << "Skip Start Cut Line:" << j + 1;
                            continue;
                        }
                        if (endLine >= 0 && j > endLine)
                        {
                            MqDebug() << "Skip End Cut Line:" << j + 1;
                            continue;
                        }

                        //如果是第一条线，并且层数
                        if (j == startLine && i < iTargetLayer)
                        {
                            continue;
                        }

                        AddCalcuPosSig((VST_Work_Main*)m_pNextState, iSideID, j, i);

                        //半切刀痕检测或定位只在第一次执行
                        if (i == 0)
                        {
                            //只在第一层时检查刀痕
                            CProcess_Level* pLevel = GET_PROCESS(PROCESS_LEVELING,
                                                                 SM_MAIN, CProcess_Level);
                            bool bAlignCheck = pLevel->m_Variants.get_VData(Var_Process_EnableHalfcut_Check)->toBool();
                            if (bAlignCheck)
                            {
                                AddHalfKerfSig((VST_Work_Main*)m_pNextState, iSideID, j, i);
                            }
                            else
                            {
                                AddTargetSig((VST_Work_Main*)m_pNextState, iSideID, j, i);
                            }
                        }

                        //切割
                        //第一条线的时候
                        //startLine不启用的时候是传入的0
                        if (j == startLine && iTargetLayer == i)
                        {
                            AddCutSig((VST_Work_Main*)m_pNextState, iSideID, j, i, iTargetTimes);
                        }
                        else
                        {
                            AddCutSig((VST_Work_Main*)m_pNextState, iSideID, j, i, 0);
                        }

                        //切割后Kerf
                        //切割后刀痕检测
                        AddKerfSig((VST_Work_Main*)m_pNextState, iSideID, j, i);
                    }
                }
            }

			((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
				pushback_Msg(VarMsg_Cut_Process_After_ID, 
				QObject::tr("Cut Process After Sig"), QVariantList()<<iSideID);

            ((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
        }
        m_pParent->SetState(m_pNextState);
    }else if(VarMsg_Cut_Process_Before_ID == msg.m_iID){
		int iSideId = msg.m_vlInput[0].toInt();
		CProductSide* pSide =GET_CHDIRECT(iSideId,CProductSide);
		if(pSide)pSide->WriteRecoveredData();

		CProcess_Cut* pProcessCut=GET_PROCESS(PROCESS_CUT,SM_MAIN,CProcess_Cut);
		pProcessCut->ClearRecoveredData(iSideId);
		pProcessCut->ClearRealtimeData(iSideId);
	}
	else if(VarMsg_Cut_Process_After_ID == msg.m_iID){
		int iSideId = msg.m_vlInput[0].toInt();

		m_gSystem.AddProductInfo(PROCESS_CUT, QString("Cut Side:%1 Finished %2").arg(iSideId==SIDE_A?"CH1":"CH2").arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz")));
		
	} else if(VarMsg_Align_Check_ID == msg.m_iID){
		int iSideID=msg.m_vlInput[0].toInt();
		CProductSide* pSide=GET_CHDIRECT(iSideID,CProductSide);
		QMutexLocker locker1(&pSide->m_CutLineVector.mutex);
		QMutexLocker locker2(&pSide->m_vCutParam.mutex);
		int isizeLine=pSide->m_CutLineVector.size();
		m_gSystem.ChangeSide(iSideID);
		if(!m_pNextState)
		{
			m_pNextState= new VST_Work_Main(VarState_Align_Check_ID,
				QObject::trUtf8("Align Check"),
				m_pParent,this,0);
			((VST_Work_Main*)m_pNextState)->m_iCurSide=iSideID;
			int iLineId = isizeLine / 2;
			//TODO:检查调平完后的位置是否正确
			QString info = QString("Align Check:\tat %3\n\tSIDE:%1 Line:%2")
				.arg(iSideID==SIDE_A?"CH1":"CH2").arg(iLineId+1)
				.arg(QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss zzz"));

			m_gSystem.AddProductInfo(PROCESS_CUT, info);
			LOG_INFO(info.toLocal8Bit().data());

			AddCalcuPosSig((VST_Work_Main*)m_pNextState,iSideID,iLineId,0);
			AddHalfKerfSig((VST_Work_Main*)m_pNextState,iSideID,iLineId,0,false);

			((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
		}
		m_pParent->SetState(m_pNextState);
	}
	if(VarMsg_Locate_Process_PauseAfter_ID == msg.m_iID)
	{
		//调平前暂停
		//m_gSystem.changeChannel(CAM6X,true);
		/*CMWorkTableDriver* pWorkTableDriver=GET_CARD(WORKTABLE_DRIVER,
			CMWorkTableDriver);
		CProcess_Level* pLevel=GET_PROCESS(PROCESS_LEVELING,SM_MAIN,CProcess_Level);
		Q_ASSERT(pWorkTableDriver);
		Q_ASSERT(pLevel);
		CMPointd Axis;
		pWorkTableDriver->WtToAxis(CAM6X,pLevel->m_AlignPtBase.Pt,Axis);
		m_gSystem.absmove_xy(Axis.tX,Axis.tY);
		m_gSystem.changeChannel(CAM6X,false);*/

		//通知暂停
		m_gSystem.m_SysMsg.SetMsg(QObject::trUtf8("Please check location status"));

		m_gSystem.m_cellTime.PauseTime();
		m_pParent->pushfront_Msg(VarMsg_Pause_ID, QObject::trUtf8("Pause Sig"));
	}else if(VarMsg_Align_Process_PauseAfter_ID == msg.m_iID)
	{
		//切割前暂停
		//m_gSystem.changeChannel(CAM6X,true);
		CMWorkTableDriver* pWorkTableDriver=GET_CARD(WORKTABLE_DRIVER,
			CMWorkTableDriver);
		CProcess_Level* pLevel=GET_PROCESS(PROCESS_LEVELING,SM_MAIN,CProcess_Level);
		Q_ASSERT(pWorkTableDriver);
		Q_ASSERT(pLevel);
		CMPointd Axis;
		pWorkTableDriver->WtToAxis(CAM6X,pLevel->m_AlignPtBase.Pt,Axis);
		m_gSystem.absmove_xy(Axis.tX,Axis.tY);
		m_gSystem.changeChannel(CAM6X,false);

		m_gSystem.m_cellTime.PauseTime();

		//通知暂停
		m_gSystem.m_SysMsg.SetMsg(QObject::trUtf8("Please check leveling status"));

		m_pParent->pushfront_Msg(VarMsg_Pause_ID, QObject::trUtf8("Pause Sig"));
	}else if(VarMsg_Debug_Align_Process_ID == msg.m_iID){
		int iSideID=msg.m_vlInput[0].toInt();
		m_gSystem.ChangeSide(iSideID);
		//模拟直接生成切割道
		CProductSide* pSide=GET_CHDIRECT(iSideID,CProductSide);
		Q_ASSERT(pSide);

		CProcess_Level* process = GET_PROCESS(PROCESS_LEVELING, SM_MAIN, CProcess_Level);

		pSide->m_CutLineVector.clear();
		process->calcuLineCircle(iSideID);
	}
	if(VarMsg_Resume_Process_Main_ID == msg.m_iID){
		//恢复记时
		m_gSystem.m_cellTime.StartTime();
	}
    if(VarMsg_Kerf_Process_ID==msg.m_iID)
    {
        int iSideID=msg.m_vlInput[0].toInt();
        int iLineID=msg.m_vlInput[1].toInt();
        int iLayerID=msg.m_vlInput[2].toInt();

        if(!m_pNextState)
        {
            m_pNextState= new VST_Work_Main(VarState_Kerf_Process_ID,
                                            QObject::trUtf8("Kerf Line"),
                                            m_pParent,this,0);

            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Process_ID,
                                 QObject::trUtf8("Calcu Kerf Pos"),
                                 QVariantList()<<PROCESS_KERFCHECK
                                 <<CProcess_Kerf::CALCUKERFPOS
                                 <<iSideID<<iLineID<<iLayerID);

            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Process_ID,
                                 QObject::trUtf8("Move Kerf Pos"),
                                 QVariantList()<<PROCESS_KERFCHECK
                                 <<CProcess_Kerf::MOVEKERFPOS );

			//Kerf检查
            ((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Process_ID,
                                 QObject::trUtf8("Search Kerf Pos"),
                                 QVariantList()<<PROCESS_KERFCHECK
								 //<<CProcess_Kerf::KERF_WATCH
                                 <<CProcess_Kerf::KERF
                                 <<iSideID<<iLayerID<<true);
            ((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
        }
        m_pParent->SetState(m_pNextState);
    }

	if(VarMsg_Kerf_LaserCali_Process_ID == msg.m_iID)
	{
		int iSideID=msg.m_vlInput[0].toInt();
		int iLineID=msg.m_vlInput[1].toInt();
		int iLayerID=msg.m_vlInput[2].toInt();

		if(!m_pNextState)
		{
			m_pNextState= new VST_Work_Main(VarState_Kerf_LaserCheck_Process_ID,
				QObject::trUtf8("Kerf Laser Line"),
				m_pParent,this,0);

			((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
				pushback_Msg(VarMsg_Process_ID,
				QObject::trUtf8("Calcu pt by Line Sig"),
				QVariantList()
				<<PROCESS_LEVELING
				<<CProcess_Level::CALCU_PT_BY_LINE
				<<iSideID<<iLineID,0);

			((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
				pushback_Msg(VarMsg_Process_ID,
				QObject::trUtf8("Calcu Kerf Pos"),
				QVariantList()<<PROCESS_LASERKERF
				<<CProcess_LaserKerf::CUTKERFLINE
				<<iSideID<<iLineID<<iLayerID);

			((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
				pushback_Msg(VarMsg_Process_ID,
				QObject::trUtf8("Move Kerf Pos"),
				QVariantList()<<PROCESS_LASERKERF
				<<CProcess_LaserKerf::MOVEKERFPOS );

			//Kerf检查
			((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
				pushback_Msg(VarMsg_Process_ID,QObject::trUtf8("Calcu pt by Line Sig"),
				QVariantList()<<PROCESS_LASERKERF
				<<CProcess_LaserKerf::KERF
				<<iSideID<<0/*Layer*/,0);


			((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
		}
		m_pParent->SetState(m_pNextState);
	}
	else if(VarMsg_Kerf_HalfCut_Process_ID == msg.m_iID){
		int iSideID=msg.m_vlInput[0].toInt();
		int iLineID=msg.m_vlInput[1].toInt();
		int iLayerID=msg.m_vlInput[2].toInt();
		bool bAlignCheck = msg.m_vlInput[3].toBool();

		//半切状态检查
		if(!m_pNextState)
		{
			m_pNextState= new VST_Work_Main(VarState_Kerf_HalfCut_Process_ID,
				QObject::trUtf8("Half Cut Kerf Line"),
				m_pParent,this,0);


			((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
				pushback_Msg(VarMsg_Process_ID,
				QObject::trUtf8("Calcu pt by Line Sig"),
				QVariantList()
				<<PROCESS_LEVELING
				<<CProcess_Level::CALCU_PT_BY_LINE
				<<iSideID<<iLineID,0);

			((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
				pushback_Msg(VarMsg_Process_ID,QObject::trUtf8("Cut kerf line"),
				QVariantList()<<PROCESS_HALFKERF
				<<CProcess_HalfCutKerf::CALCUKERFPOS
				<<iSideID<<iLineID<<0/*Layer*/,0);

			((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
				pushback_Msg(VarMsg_Process_ID, QObject::trUtf8("Move Kerf P"),
				QVariantList()<<PROCESS_HALFKERF
				<<CProcess_HalfCutKerf::MOVEKERFPOS,0);

			((VST_Work_Main*)m_pNextState)->m_VarMsgProcess.
				pushback_Msg(VarMsg_Process_ID,QObject::trUtf8("Calcu pt by Line Sig"),
				QVariantList()<<PROCESS_HALFKERF
				<<CProcess_HalfCutKerf::KERF
				<<iSideID<<iLineID<<bAlignCheck,0);

			((VST_Work_Main*)m_pNextState)->LoadMsgProcess();
		}
		m_pParent->SetState(m_pNextState);
	}
    ///////////////////////加工 结束
    VST_Work_Base::do_Msg(msg);
}

void VST_Work_Main::Enter()
{
    switch(m_iID)
    {
    case VarState_Locate_Process_ID:
        m_gSystem.m_iCurProcessID=PROCESS_LOCATE;
        break;
    case VarState_Align_Process_ID:
    case VarState_Align_PtBase_MoveSearch_ID:
	case VarState_Align_Check_ID:
        m_gSystem.m_iCurProcessID=PROCESS_LEVELING;
        break;
	case VarState_Kerf_Process_ID:
	case VarState_Kerf_HalfCut_Process_ID:
	case VarState_Kerf_LaserCheck_Process_ID:
		m_gSystem.m_iCurProcessID=PROCESS_KERFCHECK;
		break;
    case VarState_Cut_Process_ID:
        m_gSystem.m_iCurProcessID=PROCESS_CUT;
        break;

    }
    VST_Work_Base::Enter();
}

void VST_Work_Main::AddCalcuPosSig(VST_Work_Main *pNextState, int iSideID,
                                   int iLineIndex, int iLayerIndex)
{
    pNextState->m_VarMsgProcess.
            pushback_Msg(VarMsg_Process_ID,
                         QObject::trUtf8("Calcu Line Align Pos Sig"),
                         QVariantList()<<PROCESS_LEVELING
                         <<CProcess_Level::CALCU_PT_BY_LINE<<iSideID<<iLineIndex);

    //pNextState->m_VarMsgProcess.
    //        pushback_Msg(VarMsg_Process_ID,
    //                     QObject::trUtf8("Calcu Kerf Pos Sig"),
    //                     QVariantList()<<PROCESS_KERFCHECK
    //                     <<CProcess_Kerf::CALCUKERFPOS
    //                     <<iSideID<<iLineIndex<<iLayerIndex);
}

void VST_Work_Main::AddTargetSig(VST_Work_Main *pNextState, int iSideID,
                                 int iLineIndex, int iLayerIndex)
{
	//HACK:discard
    if(NeedTarget(iSideID,iLineIndex,iLayerIndex))
    {
        pNextState->m_VarMsgProcess.
                pushback_Msg(VarMsg_Align_Base_ID,
                             QObject::trUtf8("Target  Sig"),
                             QVariantList()<<iSideID<<iLineIndex);
    }
}

void VST_Work_Main::AddCutSig(VST_Work_Main *pNextState, int iSideID,
                              int iLineIndex, int iLayerIndex, int iTimes)
{
    pNextState->m_VarMsgProcess.
            pushback_Msg(VarMsg_Process_ID,QObject::trUtf8("Cut Single Line"),
                         QVariantList()<<PROCESS_CUT
                         <<CProcess_Cut::CUT_CUTLINE<<iSideID
                         <<iLineIndex<<iLayerIndex<<iTimes);
}

void VST_Work_Main::AddKerfSig(VST_Work_Main *pNextState, int iSideID,
                               int iLineIndex, int iLayerIndex)
{
    if(NeedKerf(iSideID,iLineIndex,iLayerIndex))
    {
        pNextState->m_VarMsgProcess.
                pushback_Msg(VarMsg_Kerf_Process_ID,
                             QObject::trUtf8("Kerf  Sig"),
                             QVariantList()<<iSideID<<iLineIndex);
    }
}

void VST_Work_Main::AddHalfKerfSig(VST_Work_Main* pNextState,int iSideID,int iLineIndex,int iLayerIndex, bool bCheckNeed)
{
	if(bCheckNeed){
		if(NeedTarget(iSideID,iLineIndex,iLayerIndex))
		{
			pNextState->m_VarMsgProcess.
				pushback_Msg(VarMsg_Kerf_HalfCut_Process_ID,
				QObject::trUtf8("Half Cut Kerf  Sig"),
				QVariantList()<<iSideID<<iLineIndex<<iLayerIndex<<false);
		}
	}else{
		pNextState->m_VarMsgProcess.
			pushback_Msg(VarMsg_Kerf_HalfCut_Process_ID,
			QObject::trUtf8("Location Check (Halfcut) Sig"),
			QVariantList()<<iSideID<<iLineIndex<<iLayerIndex<<true);
	}
}

void VST_Work_Main::AddKerfLaserCutSig(VST_Work_Main *pNextState, int iSideID,
	int iLineIndex, int iLayerIndex)
{
	if(NeedTarget(iSideID,iLineIndex,iLayerIndex))
	{
		pNextState->m_VarMsgProcess.
			pushback_Msg(VarMsg_Kerf_LaserCali_Process_ID,
			QObject::trUtf8("Laser Kerf  Sig"),
			QVariantList()<<iSideID<<iLineIndex);
	}
}

//判断是否使用二次定位功能
bool VST_Work_Main::NeedTarget(int iSideID, int iLineIndex, int iLayerIndex)
{
    CProductSide* pSide=GET_CHDIRECT(iSideID,CProductSide);
    int iSizeVector=pSide->m_CutLineVector.size();
    SINGLECUTPARAM Param=pSide->m_vCutParam[iLayerIndex];
    if(Param.iKerfStyle!=KERF_ONLY)
    {
        if(Param.iKerfFreq&&!((iLineIndex+1)%Param.iKerfFreq))
        {
            if(Param.iKerfFirst>0&&(iLineIndex+1)>Param.iKerfFirst&&
                    (iLineIndex+1)<iSizeVector-Param.iKerfFirst)
            {
                return true;
            }
        }
        if(Param.iKerfFirst&&(iLineIndex+1)==Param.iKerfFirst)
        {
            return true;
        }
    }
    return false;
}
//判断是否使用Kerf检查功能
bool VST_Work_Main::NeedKerf(int iSideID, int iLineIndex, int iLayerIndex)
{
    CProductSide* pSide=GET_CHDIRECT(iSideID,CProductSide);
    int iSizeVector=pSide->m_CutLineVector.size();
    SINGLECUTPARAM Param=pSide->m_vCutParam[iLayerIndex];
    if(Param.iKerfStyle!=TARGET_ONLY)
    {
        if(Param.iKerfFreq&&!((iLineIndex+1)%Param.iKerfFreq))
        {
			//如果是在步进切割道上，则返回true
            if(Param.iKerfFirst>0&&(iLineIndex+1)>Param.iKerfFirst&&
                    (iLineIndex+1)<iSizeVector-Param.iKerfFirst)
            {
                return true;
            }
        }
        if(Param.iKerfFirst&&(iLineIndex+1)==Param.iKerfFirst)
        {
            return true;
        }
    }
    return false;
}
