#include "vst_wait_schedular.h"
#include "ctransfer_manager.h"
#include "msg_def.h"
#include "vst_work_schedular.h"
#include "vsmt_main.h"
#include "cprocess_trans.h"
#include "cmallsystem.h"
#include "cprocess_scan.h"
#include "secsmanager.h"
#include "cmworktabledriver.h"

#define pStateInstance() static_cast<VST_Work_Schedular*>(m_pNextState)
VstAutoSchedular::VstAutoSchedular(int iID, const QString& sName, VSM_Thread* pParent)
    : VST_Wait_Base(iID, sName, pParent)
{

}

void VstAutoSchedular::do_Msg(const V_Msg& msg)
{
    if (IsQueueEmpty())
    {

        //自动为空的时候，启动添加VarMsg_Transfer_CheckState消息
        pushback_Msg(VarMsg_Transfer_CheckState,
                     QObject::trUtf8("Check Transfer State"));
        MSleep(10);
    }
    VSMT_Base* psmSelf = static_cast<VSMT_Base*>(m_pParent);
    VSMT_Base* psmTrans = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_TRANS));
    VSMT_Base* psmUnload = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTUnload));
    VSMT_Base* psmLoad = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTLoad));
    VSMT_Base* psmMain = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_MAIN));
    VSMT_Base* psmCoat = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_COAT));
    VSMT_Base* psmClean = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_CLEAN));

    switch (msg.m_iID)
    {
        case VarMsg_StartAuto_ID:
        {
            m_gSystem.m_totalWorkTime.StartTime();
            m_gSystem.m_fullAutoTime.ClearTime();
            m_gSystem.m_fullAutoTime.StartTime();
            m_gSystem.WriteRecoverData();

            g_SecsManager.SendEvent(EVENT_JobStarted);
            //扫描料盒及准备
            if (!m_pNextState)
            {
                m_pNextState = new VST_Work_Schedular(VarState_Wait_Schedular,
                                                      QObject::trUtf8("Auto prepare"), m_pParent, this, 0);

                pStateInstance()->m_VarMsgProcess.
                    pushback_Msg(VarMsg_Schedular_Prepare, QObject::trUtf8("Auto prepare"));
                pStateInstance()->LoadMsgProcess();
            }
            m_pParent->SetState(m_pNextState);
            //切割平台初始化操作
            break;
        }
        case VarMsg_Transfer_CheckState:
        {
            CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS, SM_TRANS, CProcess_Trans);
            QMutexLocker l(&processTrans->m_slotMutex);
            //依次从后往前处理晶圆
            if (ProcessCupboardManualCheck())
            {
                LOG_INFO(">>ProcessCupboardManualCheck");
                MqDebug() << "ProcessRailNear";
            }
            else if (ProcessRailNear())
            {
                LOG_INFO(">>ProcessRailNear");
                MqDebug() << "ProcessRailNear";
            }
            else if (ProcessRailFar())
            {
                LOG_INFO(">>ProcessRailFar");
                MqDebug() << "ProcessRailFar";
            }
            else if (ProcessCheckBox())
            {
                LOG_INFO(">>ProcessCheckBox");
                MqDebug() << "ProcessCheckBox";
            }
            else if (ProcessClean())
            {
                LOG_INFO(">>ProcessClean");
                MqDebug() << "ProcessClean";
            }
            else if (ProcessCoat())
            {
                LOG_INFO(">>ProcessCoat");
                MqDebug() << "ProcessCoat";
            }
            else if (ProcessUnload())
            {
                LOG_INFO(">>ProcessUnload");
                MqDebug() << "ProcessUnload";
            }
            else if (ProcessWorktable())
            {
                LOG_INFO(">>ProcessWorktable");
                MqDebug() << "ProcessWorktable";
            }
            else if (ProcessLoad())
            {
                LOG_INFO(">>ProcessLoad");
                MqDebug() << "ProcessLoad";
            }
            else if (ProcessCasste())
            {
                LOG_INFO(">>ProcessCasste");
                MqDebug() << "ProcessCasste";
            }
            else
            {
                //MqDebug() << "No Process Schedular";
            }

            break;
        }
#if 0
        case VarMsg_Auto_CutScan:
        {
            CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
            bool bIsCutFinished = pCass->IsCassCutFinished();
            if (bIsCutFinished)
            {
                CMWorkTableDriver* pWorkTableDriver = GET_CARD(WORKTABLE_DRIVER,
                                                               CMWorkTableDriver);

                pWorkTableDriver->ManualLoadPos(WORKTABLE);

                CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS, SM_TRANS, CProcess_Trans);
                processTrans->MoveHGrabWait();

                CProcess_Scan* pCass = GET_PROCESS(PROCESS_SCAN, SM_TRANS,
                                                   CProcess_Scan);
                pCass->CassUp(CASSETTE);

                m_gSystem.EvtLog(QString::fromUtf8("FAE"),
                                 QObject::trUtf8("Cassette Cut Finished"));
                //结束计时
                m_gSystem.m_totalWorkTime.StopTime();
                m_gSystem.m_fullAutoTime.StopTime();
                m_gSystem.m_totalWorkHour += m_gSystem.m_totalWorkTime.GetTime() / 3600;
                m_gSystem.m_totalWorkTime.ClearTime();

                int maxCycleCount = m_gSystem.m_Variants.get_VData(Var_MaxCycle_Count)->toInt();
                if (m_gSystem.m_bEnableCycle
                    && (maxCycleCount <= 0 || (maxCycleCount > 0 && m_gSystem.m_iTotalCuttedWafer < maxCycleCount)))
                {
                    clear_Msg();
                    pushback_Msg(VarMsg_StartAuto_ID,
                                 QObject::trUtf8("Restart auto cycle"));
                }
                else
                {
                    g_SecsManager.SendEvent(EVENT_JobComplete);
                    m_gSystem.publish_msg(V_Msg(VarMsg_Stop_ID,
                                          QObject::trUtf8("Cut Finished,Stop All")));
                    m_gSystem.m_SysMsg.SetMsg(QObject::trUtf8("Cassette Cut Finished"));
                }
                return;
            }

            //TODO:提前终止
            CProcess_Trans* pTrans = GET_PROCESS(PROCESS_TRANS,
                                                 SM_TRANS, CProcess_Trans);
            Q_ASSERT(pTrans);

            if (!pTrans->m_pSlotCoat && pCass->GetFirstUnCutWafer() && psmTrans->IsWaitTask())
            {
                //转移到涂敷台
                AddMsgToState(SM_TRANS, CProcess_Trans::TRANSCASSTOCOAT,
                              QObject::trUtf8("Cass to CoatTable"));

                //开始涂覆
                /*QString strStart = QObject::trUtf8("Auto Coat Start");
                pushfront_Msg(VarMsg_Auto_StartCoat, strStart);*/

                CASSSLOT* pSlot = pCass->GetFirstUnCutWafer();
                pSlot->BeginDate = QDateTime::currentDateTime();
                int iSlotID = pSlot->index + 1;

                QString str = QObject::trUtf8("DNo:%1,DID:%2,TM:%3")
                    .arg(m_gSystem.GetCurFile())
                    .arg(iSlotID)
                    .arg(pSlot->BeginDate.toString("hh:mm:ss"));
                m_gSystem.EvtLog(QString::fromUtf8("JOB_START"), str);
            }
            else if (pTrans->m_pSlotCoat && pTrans->m_pSlotCoat->WPstatus == WPCOAT &&
                     psmCoat->IsWaitTask())
            {
                //开始涂覆
                V_Msg msg;
                msg.m_iID = VarMsg_Auto_StartCoat;
                msg.m_sName = QObject::trUtf8("Auto Coat Start");;
                AddMsgToSM(SM_COAT, msg);
            }
            else if (pTrans->m_pSlotWT && pTrans->m_pSlotWT->WPstatus == WPCUT &&
                     psmMain->IsWaitTask())
            {
                V_Msg msg;
                msg.m_iID = VarMsg_Auto_StartCut;
                msg.m_sName = QObject::trUtf8("Auto Cut Start");;
                MqDebug() << "------ cut" << pTrans->m_pSlotWT->index;
                AddMsgToSM(SM_MAIN, msg);
            }
            else if (pTrans->m_pSlotClean && pTrans->m_pSlotClean->WPstatus == WPCLEAN &&
                     psmClean->IsWaitTask())
            {
                V_Msg msg;
                msg.m_iID = VarMsg_Auto_StartClean;
                msg.m_sName = QObject::trUtf8("Auto Clean Start");;
                AddMsgToSM(SM_CLEAN, msg);
            }
            else if (pTrans->m_pSlotClean && pTrans->m_pSlotClean->WPstatus == WPCLEANFINISH
                     && psmTrans->IsWaitTask())
            {
                //清洗台有晶圆，并且清洗完成，转移到料盒或CheckBox
                CProcess_Scan* pScan = GET_PROCESS(PROCESS_SCAN, SM_TRANS, CProcess_Scan);
                Q_ASSERT(pScan);
                AddMsgToState(SM_TRANS, CProcess_Trans::TRANSCLEANTOCASS,
                              QObject::trUtf8("CleanTable to Cass"));

            }
            else if (pTrans->m_pSlotWT && pTrans->m_pSlotWT->WPstatus == WPCUTFINISH
                     && !pTrans->m_pSlotClean && psmTrans->IsWaitTask())
            {
                //平台有晶圆，并且切割完成，并且没有未清洗的晶圆
                AddMsgToState(SM_WTUnload, CProcess_Trans::TRANSWTTOCLEAN,
                              QObject::trUtf8("WT to CleanTable"));

                /*QString strStart = QObject::trUtf8("Auto Clean Start");
                pushfront_Msg(VarMsg_Auto_StartClean, strStart);*/
            }
            else if (pTrans->m_pSlotCoat && pTrans->m_pSlotCoat->WPstatus == WPCOATFINISH
                     && !pTrans->m_pSlotWT && psmTrans->IsWaitTask())
            {
                //转移到平台
                AddMsgToState(SM_WTLoad, CProcess_Trans::TRANSCOATTOWT,
                              QObject::trUtf8("CleanTable to WorkTable"));

                /*QString strStart = QObject::trUtf8("Auto Cut Start");
                pushfront_Msg(VarMsg_Auto_StartCut, strStart);*/
            }

            //直接跳出去
            break;
#if 0
            {
                //检查待处理的晶圆，依次进行处理
                //slot的状态

                //1.如果任务队列空闲了，可以分派任务
                    //虚假的工位空闲，有可能下次任务在队列中还未执行            

                //2.依次检查各个位置的晶圆，从后往前，依次处理掉
                    //如果

                CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS, SM_TRANS, CProcess_Trans);
                //近轨道有料
                if (processTrans->m_pSlotRailNear &&
                    !processTrans->m_pSlotRailNear->bProcessing)
                {
                    VSM_Thread* pSM = m_gSystem.FindSM(SM_TRANS);
                    Q_ASSERT(pSM);
                    if (!pSM->IsWaitTask())
                    {
                        //传片不空闲，继续等待
                        return;
                    }

                    ///
                    //UNSCANED,
                    //    NOWP,   //没有Wafer
                    //    WPUNCUT,
                    //    WPMALPOSED,	//错位
                    //    WPOVERLAPPED,	//叠片
                    //    SCANFAILED,
                    //    TOGRAB,
                    //    TOCOAT,
                    //    WPCOAT,
                    //    WPCOATFINISH,
                    //    TOCUT,
                    //    WPCUT,
                    //    WPCUTFINISH,
                    //    TOCLEAN,
                    //    WPCLEAN,
                    //    WPCLEANFINISH,
                    //    TOUNLOAD,
                    //    WPCUTTED,   //切割完毕
                    //    WPABORT,
                    //    WPCHECKING,
                    //    WPCHECKED,

                    //Transfer上面不能中转
                    CASSSLOT* pSlot = processTrans->m_pSlotRailNear;
                    if (pSlot->bCleanFinished)
                    {
                        //To Checkbox or Cassete
                        if (pSlot->bNeedCheckCut)
                        {
                            if (pSlot->bCheckCutFinished)
                            {
                                //Cut检查完成

                                //放到
                                //Rail1 TO Cassete
                                VSM_Thread* psmUnload = m_gSystem.FindSM(SM_WTUnload);
                                if (psmUnload->IsWork())
                                {
                                    //Wait
                                }
                            }
                            else
                            {
                                //TO CheckBox
                                //调度异常
                                Q_ASSERT(!processTrans->m_pSlotCheckBox);
                            }
                        }
                        else
                        {
                            //TO Cassete
                            //Rail1 TO Cassete
                            VSM_Thread* psmUnload = m_gSystem.FindSM(SM_WTUnload);
                            if (psmUnload->IsWork())
                            {
                                //Wait
                            }
                        }

                    }
                    else if (pSlot->bCutFinished)
                    {
                        //To Clean
                        VSM_Thread* psmUnload = m_gSystem.FindSM(SM_WTUnload);
                        if (psmUnload->IsWork())
                        {
                            //Wait
                        }
                    }
                    else if (pSlot->bCoatFinished)
                    {
                        //To Wt or To checkbox
                        if (pSlot->bNeedCheckCoat)
                        {
                            if (pSlot->bCheckCoatFinished)
                            {
                                //涂覆检查完成

                                //放到平台上去
                                //TO WT
                            }
                            else
                            {
                                //TO CheckBox
                                //调度异常
                                Q_ASSERT(!processTrans->m_pSlotCheckBox);
                            }

                        }

                    }
                    else
                    {
                        //To Coat
                        if (processTrans->m_pSlotCoat || processTrans->m_pSlotRailFar)
                        {
                            //coat有料，且Rail2有料不能处理
                        }

                        VSM_Thread* psmUnload = m_gSystem.FindSM(SM_WTUnload);
                        VSM_Thread* psmLoad = m_gSystem.FindSM(SM_WTLoad);
                        if (psmUnload->IsWork() || psmUnload->IsWork())
                        {
                            //To Coat 上下料工作中，不能调度
                            //WaitSchedular
                        }

                        //直接到Coat
                        //先到Rail2,再到Coat
                    }
                }

                if (processTrans->m_pSlotRailFar)
                {
                    CASSSLOT* pSlot = processTrans->m_pSlotRailNear;
                    if (pSlot->bEnableCut)
                    {
                        if (pSlot->bCutFinished)
                        {
                            //切割完成？？？
                        }
                        else
                        {
                            //未切割
                            //TOWT //上料
                            processTrans->m_pSlotWT;
                            if (psmLoad->IsWork() || psmUnload->IsWork())
                            {
                                //Wait
                            }


                        }
                    }

                    Q_ASSERT(0);
                }

                if (processTrans->m_pSlotCheckBox)
                {
                    CASSSLOT* pSlot = processTrans->m_pSlotRailNear;
                    if (psmTrans->IsWork())
                    {
                        //Wait
                    }

                }

                if (processTrans->m_pSlotCoat && processTrans->m_pSlotCoat->WPstatus == WPCOAT)
                {
                    if (psmCoat->IsWaitTask())
                    {

                        if (ResManager().CanAcquire(SM_COAT, kResCoat))
                        {
                            V_Msg msg;
                            msg.m_iID = VarMsg_Auto_StartCoat;
                            msg.m_sName = QObject::trUtf8("Auto Coat Start");;
                            AddMsgToSM(SM_COAT, msg);
                            MqDebug() << "Schedular" << "Auto Coat Start";
                        }

                    }
                }

                //检查料盒
                CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
                bool bIsCutFinished = pCass->IsCassCutFinished();
                if (bIsCutFinished)
                {
                    CMWorkTableDriver* pWorkTableDriver = GET_CARD(WORKTABLE_DRIVER,
                                                                   CMWorkTableDriver);

                    pWorkTableDriver->ManualLoadPos(WORKTABLE);

                    CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS, SM_TRANS, CProcess_Trans);
                    processTrans->MoveToPosGrabWait();

                    CProcess_Scan* pCass = GET_PROCESS(PROCESS_SCAN, SM_TRANS,
                                                       CProcess_Scan);
                    pCass->CassUp(CASSETTE);

                    m_gSystem.EvtLog(QString::fromUtf8("FAE"),
                                     QObject::trUtf8("Cassette Cut Finished"));
                    //结束计时
                    m_gSystem.m_totalWorkTime.StopTime();
                    m_gSystem.m_fullAutoTime.StopTime();
                    m_gSystem.m_totalWorkHour += m_gSystem.m_totalWorkTime.GetTime() / 3600;
                    m_gSystem.m_totalWorkTime.ClearTime();

                    int maxCycleCount = m_gSystem.m_Variants.get_VData(Var_MaxCycle_Count)->toInt();
                    if (m_gSystem.m_bEnableCycle
                        && (maxCycleCount <= 0 || (maxCycleCount > 0 && m_gSystem.m_iTotalCuttedWafer < maxCycleCount)))
                    {
                        clear_Msg();
                        pushback_Msg(VarMsg_StartAuto_ID,
                                     QObject::trUtf8("Restart auto cycle"));
                    }
                    else
                    {
                        g_SecsManager.SendEvent(EVENT_JobComplete);
                        m_gSystem.publish_msg(V_Msg(VarMsg_Stop_ID,
                                              QObject::trUtf8("Cut Finished,Stop All")));
                        m_gSystem.m_SysMsg.SetMsg(QObject::trUtf8("Cassette Cut Finished"));
                    }
                    return;
                }

                if (pCass->GetFirstUnCutWafer() && !processTrans->m_pSlotCoat)
                {
                    CASSSLOT* pSlot = pCass->GetFirstUnCutWafer();
                    ////如果是首片，直接走
                    //if (pCass->IsSlotFirstInCass(pSlot)) {
                    //    //设置首片检查
                    if (psmTrans->IsWaitTask())
                    {
                        if (ResManager().CanAcquire(SM_TRANS, kResCoat))
                        {
                            ResManager().Acquire(SM_TRANS, kResCoat);
                            if (true == AddMsgToSMState(SM_TRANS, CProcess_Trans::TRANSCASSTOCOAT,
                                QObject::trUtf8("Cass to CoatTable")))
                            {

                            }
                        }

                    }
                    //添加一个finish消息
                        /*    QString strStart = QObject::trUtf8("Auto Coat Start");
                            pushfront_Msg(VarMsg_Auto_StartCoat, strStart);
                        }*/
                }

            }

            //CTransferManager* transferManager;
            ////获取待加工Wafer
            ////处理调度逻辑
            //CProcess_Trans* processTrans;
            //if (processTrans->m_pSlotGrab) {

            //} else if (processTrans->m_pSlotRailNear && ProcessCassWafer()) {

            //}

            //

            //int ProcessTransWafer();
            //int ProcessRailNearWafer();
            //int ProcessRailFarWafer();
            //int ProcessCheckboxWafer();
            //int ProcessCleanWafer();
            //int ProcessUnloadWafer();
            //int ProcessWtWafer();
            //int ProcessLoadWafer();
            //int ProcessCoatWafer();
            //int ProcessCassWafer();
            //


            //AnalyseTask();

            //传片
                //1.放回料盒
                //2.放回检查盒
                //3.

            //2.工位暂停状态，不能分派任务

            //3.条件不满足，暂停分派任务

            //coat
            //clean
            //unload
            //load
            //trans



            //TODO:提前终止
           /* CProcess_Trans* pTrans = GET_PROCESS(PROCESS_TRANS,
                                                 SM_TRANS, CProcess_Trans);

            Q_ASSERT(pTrans);


            if(p)*/

            //TODO：同时竞争往料盒放的时候，就发生问题，需要处理
            //优先把Cupboard里面的处理了，就没有竞争的情况了
            //从后往前
            //if (pTrans->m_pSlotCheckBox&&pTrans->m_pSlotCheckBox->CheckStatus == CHECKCUTING) {
            //    //暂停等待检查
            //    m_gSystem.FindSM(SM_TRANS)->pushfront_Msg(VarMsg_Pause_ID, QObject::trUtf8("Pause for check wafer cutting."));
            //    m_gSystem.m_SysMsg.SetMsg(QObject::trUtf8("Please check cuting quality on the cupboard."));

            //    g_SecsManager.SendEvent(EVENT_JobPaused);
            //    g_SecsManager.SendEvent(EVENT_CutingCheckStarted);
            //} 
#endif
        }
#endif
    }
}

void VstAutoSchedular::AddMsgToSM(int iSMId, const V_Msg& msg, bool bfront/*=false*/)
{
    VSM_Thread* pSM = m_gSystem.FindSM(iSMId);
    if (pSM->IsWaitTask())
    {
        /*if (pSM->m_pCurState == pSM->m_pState_Wait) {
            MqDebug() << "AddMsgToSM Success:"<<msg.m_sName << endl;

        }*/
        pSM->pushBack_Msg_toState(nullptr, msg);
    }
    else
    {
        if (pSM->IsWork())
        {

        }
        MqDebug() << "AddMsgToSM SM not started" << endl;
        return;
    }
}

//将消息委托给VST_Work_Transfer执行，内部调用CProcess_Trans的消息循环
void VstAutoSchedular::AddMsgToState(int iSvmId, int iTransMsgID, uint nAcqResId,
                                     const QString& msgName, bool bfront/*=false*/)
{
    if (!m_pNextState)
    {
        m_pNextState = new VST_Work_Schedular(VarState_Wait_Schedular,
                                              msgName, m_pParent, this, 0);

        uint nVsmResId = kResReserve;
        if (iSvmId == SM_TRANS)
        {
            nVsmResId = kVsmTransfer;
        }
        else if (iSvmId == SM_WTLoad)
        {
            nVsmResId = kVsmLoad;
        }
        else if (iSvmId == SM_WTUnload)
        {
            nVsmResId = kVsmUnload;
        }
        else if (iSvmId == SM_MAIN)
        {
            nVsmResId = kVsmWorktable;
        }
        else if (iSvmId == SM_CLEAN)
        {
            nVsmResId = kVsmClean;
        }
        else if (iSvmId == SM_COAT)
        {
            nVsmResId = kVsmCoat;
        }
        else
        {
            Q_ASSERT(0);
        }

        LOG_INFO(fmt::format("AddMsgToState:{} msgId:{} msgName:{}", iSvmId, iTransMsgID, msgName.toLocal8Bit().data()));
        MqDebug() << "AddMsgToState:" << iTransMsgID;
        pStateInstance()->m_VarMsgProcess.
            pushback_Msg(VarMsg_Schedular_Dispatch_Msg,
                         QObject::tr("Schedular Dispatch msg"),
                         QVariantList() << iSvmId
                         << iTransMsgID << msgName
                         << bfront
                         << nAcqResId
                         << nVsmResId);
        pStateInstance()->LoadMsgProcess();
    }
    else
    {
        MqDebug() << " m_pNextState  not null";
    }
    m_pParent->SetState(m_pNextState);
    //切割平台初始化操作
}
bool VstAutoSchedular::ProcessTrans()
{
    return false;
}

bool VstAutoSchedular::ProcessRailNear()
{
    CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS,
                                               SM_TRANS, CProcess_Trans);

    CASSSLOT* pSlot = processTrans->m_pSlotRailNear;
    if (!pSlot)
    {
        return false;
    }

    VSMT_Base* psmTrans = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_TRANS));
    VSMT_Base* psmUnload = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTUnload));
    VSMT_Base* psmLoad = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTLoad));
    VSMT_Base* psmMain = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_MAIN));
    VSMT_Base* psmCoat = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_COAT));
    VSMT_Base* psmClean = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_CLEAN));
    if (!psmTrans->IsWaitTask())
    {
        //MqDebug() << "Trans is wait";
        return false;
    }
    else
    {
        //MqDebug() << "Trans is not wait";
    }
    //!
    // * 1.第一次进入处理，放到涂覆台，直接放到涂覆台，不在Rail2中转
    // * 2.涂覆检查，放到检查盒
    // * 3.涂覆检查完成，放到加工台，Attention:用下料手放到加工台
    // * 4.清洗完成，检查切割，放到检查盒
    // * 5.切割检查完成，放到料盒需要检查切割且未检查
    //   6.加工完成，去清洗
    //   需要检查切割但检查完了

    if (pSlot->bNeedRelocation)
    {
        if (!ResManager().CanAcquire(SM_TRANS, kResTransfer | kResRailNear | kAreaClean))
        {
            return false;
        }

        //重新准直
        AddMsgToState(SM_TRANS, CProcess_Trans::kTransRailNearLocation,
                      (uint)kResTransfer | kResRailNear | kAreaClean);
        return true;
    }

    //4.5.已经清洗完了,一定是加工完了
    if (pSlot->bCleanFinished && pSlot->bCutFinished)
    {
        if (pSlot->bNeedCheckCut)
        {
            if (!pSlot->bCheckCutFinished)
            {
                //需要检查切割质量，还未检查,到检查盒检查
                if (processTrans->m_pSlotCheckBox)
                {
                    MQT_THROW_CODESTR(ALARM_RESERVED, QObject::tr("check box has wafer"));
                    return false;
                }

                if (!ResManager().CanAcquire(SM_TRANS, kResCheckBox | kResTransfer | kResRailNear | kAreaClean))
                {
                    return false;
                }

                //TODO: to checkbox
                AddMsgToState(SM_TRANS, CProcess_Trans::kTransRailNearToCheckBox,
                              kResCheckBox | kResTransfer | kResRailNear | kAreaClean);


                return true;
            }
            else
            {

                if (!ResManager().CanAcquire(SM_TRANS, kResCassete | kResTransfer | kResRailNear | kAreaClean))
                {
                    return false;
                }

                AddMsgToState(SM_TRANS, CProcess_Trans::kTransRailNearToCass,
                              kResCassete | kResTransfer | kResRailNear | kAreaClean);
                return true;
                //检查过的不应该在Rail上面时，Transfer没运行
                //直接放到料盒中了
                //MQT_THROW_CODESTR(ALARM_RESERVED, QObject::tr("Reil near has cut checked wafer"));
            }
        }
        else
        {
            if (!ResManager().CanAcquire(SM_TRANS, kResCassete | kResTransfer | kResRailNear | kAreaClean))
            {
                return false;
            }
            //TODO: to casste
            AddMsgToState(SM_TRANS, CProcess_Trans::kTransRailNearToCass,
                          kResCassete | kResTransfer | kResRailNear | kAreaClean);
            return true;
        }
    }

    //2.3. 仅涂覆完成，未切割，一定未清洗
    if (pSlot->bCoatFinished
        && !pSlot->bCutFinished && !pSlot->bCleanFinished)
    {
        if (pSlot->bNeedCheckCoat)
        {
            if (pSlot->bCheckCoatFinished)
            {
                //检查使用的位置是否有晶圆
                if (processTrans->m_pSlotWT || processTrans->m_pSlotUnLoad)
                {
                    return false;
                }

                //如果上下料和平台不同时工作
                if (!psmUnload->IsWaitTask()
                    || !psmMain->IsWaitTask()
                    || !psmLoad->IsWaitTask())
                {
                    return false;
                }

                //检查资源是否可用
                //注意此时如果上下料在清洗区，是不能工作的
                if (!ResManager().CanAcquire(SM_WTUnload, kResRailNear | kResWt | kResUnload
                    | kAreaClean))
                {
                    return false;
                }

                //TODO: to worktable
                AddMsgToState(SM_WTUnload, CProcess_Trans::kTransRailNearToWorktable,
                              kResRailNear | kResWt | kResUnload | kAreaClean);
                return true;
            }
            else
            {
                if (processTrans->m_pSlotCheckBox)
                {
                    MQT_THROW_CODESTR(ALARM_RESERVED, QObject::tr(""));
                    return false;
                }

                if (!psmTrans->IsWaitTask())
                {
                    return false;
                }

                if (!ResManager().CanAcquire(SM_TRANS, kResCheckBox | kResTransfer | kResRailNear | kAreaClean))
                {
                    return false;
                }

                //TODO: to checkbox
                AddMsgToState(SM_TRANS, CProcess_Trans::kTransRailNearToCheckBox,
                              kResCheckBox | kResTransfer | kResRailNear | kAreaClean);
                return true;
            }
        }

    }

    //1.未涂覆，去涂覆
    if (!pSlot->bCoatFinished)
    {
        if (!psmTrans->IsWaitTask())
        {
            return false;
        }
        //涂覆桶有料
        if (processTrans->m_pSlotCoat || processTrans->m_pSlotRailFar)
        {
            return false;
        }

        //上下料工作中，不能向涂覆桶传料
        //涂覆桶工作中
        if (!psmUnload->IsWaitTask()
            || !psmCoat->IsWaitTask()
            || !psmLoad->IsWaitTask())
        {
            return false;
        }
        //检查资源是否可用
        //注意此时如果上下料在清洗或涂覆区，是不能工作的
        if (!ResManager().CanAcquire(SM_TRANS, kResTransfer | kResRailNear | kResRailFar
            | kResCoat | kAreaClean | kAreaCoat | kResDoorOpen))
        {
            return false;
        }

        //HACK:直接到涂覆桶或者到轨道
        //TODO:railnear to coat
        AddMsgToState(SM_TRANS, CProcess_Trans::kTransRailNearToCoat,
                      kResTransfer | kResRailNear | kResRailFar
                      | kResCoat | kAreaClean | kAreaCoat | kResDoorOpen);
        return true;
    }

    //6.未清洗,去清洗
    //未清洗，已切割
    if (!pSlot->bCleanFinished && pSlot->bCutFinished)
    {
        //去清洗
        if (processTrans->m_pSlotClean || processTrans->m_pSlotTrans)
        {
            return false;
        }

        if (!psmClean->IsWaitTask()
            || !psmTrans->IsWaitTask()
            || !psmUnload->IsWaitTask())
        {
            return false;
        }

        //检查资源是否可用
        //注意此时如果上下料在清洗区，是不能工作的
        if (!ResManager().CanAcquire(SM_TRANS, kResTransfer | kResRailNear | kResClean | kAreaClean | kResDoorOpen))
        {
            return false;
        }

        //TODO: 放到清洗桶中
        AddMsgToState(SM_TRANS, CProcess_Trans::kTransRailNearToClean,
                      kResTransfer | kResRailNear | kResClean | kAreaClean | kResDoorOpen);
        return true;
    }

    return false;
}

bool VstAutoSchedular::ProcessRailNearOneRail()
{
    CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS,
                                               SM_TRANS, CProcess_Trans);

    CASSSLOT* pSlot = processTrans->m_pSlotRailNear;
    if (!pSlot)
    {
        return false;
    }

    VSMT_Base* psmTrans = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_TRANS));
    VSMT_Base* psmUnload = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTUnload));
    VSMT_Base* psmLoad = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTLoad));
    VSMT_Base* psmMain = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_MAIN));
    VSMT_Base* psmCoat = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_COAT));
    VSMT_Base* psmClean = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_CLEAN));
    if (!psmTrans->IsWaitTask())
    {
        //MqDebug() << "Trans is wait";
        return false;
    }
    else
    {
        //MqDebug() << "Trans is not wait";
    }
    //!
    // * 1.第一次进入处理，放到涂覆台，直接放到涂覆台，不在Rail2中转
    // * 2.涂覆检查，放到检查盒
    // * 3.涂覆检查完成，放到加工台，Attention:用下料手放到加工台
    // * 4.清洗完成，检查切割，放到检查盒
    // * 5.切割检查完成，放到料盒需要检查切割且未检查
    //   6.加工完成，去清洗
    //   需要检查切割但检查完了

    //4.5.已经清洗完了,一定是加工完了
    if (pSlot->bCleanFinished && pSlot->bCutFinished)
    {
        if (!psmTrans->IsWaitTask())
        {
            return false;
        }

        if (!ResManager().CanAcquire(SM_TRANS, kResCassete | kResTransfer | kResRailNear | kAreaClean))
        {
            return false;
        }

        AddMsgToState(SM_TRANS, CProcess_Trans::kTransRailNearToCass,
                      kResCassete | kResTransfer | kResRailNear | kAreaClean);
        return true;
    }

    //2.3. 仅涂覆完成，未切割，一定未清洗,去切割台
    if (pSlot->bCoatFinished
        && !pSlot->bCutFinished && !pSlot->bCleanFinished)
    {
        if (!psmUnload->IsWaitTask())
        {
            return false;
        }

        if (processTrans->m_pSlotWT)
        {
            MqDebug() << "Err::Schedular:kTransRailNearToWorktable:WT has wafer";
            return false;
        }

        if (!ResManager().CanAcquire(SM_WTUnload, kResUnload | kResRailNear | kResWt | kAreaClean))
        {
            return false;
        }

        //TODO: to checkbox
        AddMsgToState(SM_WTUnload, CProcess_Trans::kTransRailNearToWorktable,
                      kResUnload | kResRailNear | kResWt | kAreaClean);
        return true;
    }

    //1.未涂覆，去涂覆
    if (!pSlot->bCoatFinished)
    {
        if (!psmTrans->IsWaitTask())
        {
            return false;
        }
        //涂覆桶有料
        if (processTrans->m_pSlotCoat || processTrans->m_pSlotRailFar)
        {
            return false;
        }

        //上下料工作中，不能向涂覆桶传料
        //涂覆桶工作中
        if (!psmUnload->IsWaitTask()
            || !psmCoat->IsWaitTask()
            || !psmLoad->IsWaitTask())
        {
            return false;
        }
        //检查资源是否可用
        //注意此时如果上下料在清洗或涂覆区，是不能工作的
        if (!ResManager().CanAcquire(SM_TRANS, kResRailNear | kResRailFar | kResUnload
            | kAreaClean | kAreaCoat | kResDoorOpen))
        {
            return false;
        }

        //HACK:直接到涂覆桶或者到轨道
        //TODO:railnear to coat
        AddMsgToState(SM_TRANS, CProcess_Trans::kTransRailNearToCoat,
                      kResRailNear | kResRailFar | kResUnload
                      | kAreaClean | kAreaCoat | kResDoorOpen);
        return true;
    }

    //6.未清洗,去清洗
    //未清洗，已切割
    if (!pSlot->bCleanFinished && pSlot->bCutFinished)
    {
        //去清洗
        if (processTrans->m_pSlotClean || processTrans->m_pSlotTrans)
        {
            return false;
        }

        if (!psmClean->IsWaitTask()
            || !psmTrans->IsWaitTask()
            || !psmUnload->IsWaitTask())
        {
            return false;
        }

        //检查资源是否可用
        //注意此时如果上下料在清洗区，是不能工作的
        if (!ResManager().CanAcquire(SM_TRANS, kResClean | kResTransfer
            | kAreaClean | kResDoorOpen))
        {
            return false;
        }

        //TODO: 放到清洗桶中
        AddMsgToState(SM_TRANS, CProcess_Trans::kTransRailNearToClean,
                      kResClean | kResTransfer | kAreaClean | kResDoorOpen);
        return true;
    }

    return false;
}

bool VstAutoSchedular::ProcessRailFar()
{
    CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS,
                                               SM_TRANS, CProcess_Trans);

    CASSSLOT* pSlot = processTrans->m_pSlotRailFar;
    if (!pSlot)
    {
        return false;
    }

    VSMT_Base* psmTrans = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_TRANS));
    VSMT_Base* psmUnload = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTUnload));
    VSMT_Base* psmLoad = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTLoad));
    VSMT_Base* psmMain = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_MAIN));
    VSMT_Base* psmCoat = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_COAT));

    //涂覆未切割
    if (pSlot->bCoatFinished)
    {
        Q_ASSERT(!pSlot->bCutFinished && !pSlot->bCleanFinished);

        //涂覆检查
        if (pSlot->bNeedCheckCoat && !pSlot->bCheckCoatFinished)
        {
            //检查目标位置没有晶圆
            if (processTrans->m_pSlotTrans || processTrans->m_pSlotRailNear
                || processTrans->m_pSlotCheckBox)
            {
                return false;
            }

            if (!psmUnload->IsWaitTask()
                || !psmTrans->IsWaitTask()
                || !psmLoad->IsWaitTask())
            {
                return false;
            }

            if (false == ResManager().CanAcquire(SM_TRANS, kResRailFar | kResRailNear | kResTransfer
                | kAreaClean | kAreaCoat))
            {
                return false;
            }

            //TODO: to slotnear
            AddMsgToState(SM_TRANS, CProcess_Trans::kTransRailFarToRailNear,
                          kResRailFar | kResRailNear | kResTransfer
                          | kAreaClean | kAreaCoat);
            return true;
        }
        else
        {
            //到平台
            if (processTrans->m_pSlotWT || processTrans->m_pSlotLoad)
            {
                return false;
            }

            //如果上下料和平台不同时工作
            if (!psmUnload->IsWaitTask()
                || !psmMain->IsWaitTask()
                || !psmLoad->IsWaitTask())
            {
                return false;
            }

            //检查资源是否可用
            //注意此时如果上下料在清洗区，是不能工作的
            if (!ResManager().CanAcquire(SM_WTLoad, kResWt | kResLoad
                | kAreaCoat))
            {
                return false;
            }

            //TODO: RailFra to Wt
            AddMsgToState(SM_WTLoad, CProcess_Trans::kTransRailFarToWorktable,
                          kResLoad | kResRailFar | kResWt | kAreaCoat);
            return true;
        }
    }
    else
    {
        //HACK:直接放到桶里了，则不处理
        //去涂覆
        if (processTrans->m_pSlotCoat || processTrans->m_pSlotTrans)
        {
            return false;
        }

        if (!psmCoat->IsWaitTask()
            || !psmTrans->IsWaitTask()
            || !psmLoad->IsWaitTask())
        {
            return false;
        }

        //检查资源是否可用
        //注意此时如果上下料在清洗区，是不能工作的
        if (!ResManager().CanAcquire(SM_TRANS, kResCoat | kResTransfer
            | kAreaCoat | kResDoorOpen))
        {
            return false;
        }

        //TODO: 放到涂覆桶中
        AddMsgToState(SM_TRANS, CProcess_Trans::kTransRailFarToCoat,
                      kResCoat | kResTransfer | kAreaCoat | kResDoorOpen);
        return true;
    }

    return false;

}

bool VstAutoSchedular::ProcessCheckBox()
{
    CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS,
                                               SM_TRANS, CProcess_Trans);

    CASSSLOT* pSlot = processTrans->m_pSlotCheckBox;
    if (!pSlot)
    {
        return false;
    }

    VSMT_Base* psmTrans = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_TRANS));
    VSMT_Base* psmUnload = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTUnload));
    VSMT_Base* psmLoad = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTLoad));
    VSMT_Base* psmMain = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_MAIN));
    VSMT_Base* psmCoat = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_COAT));

    if (processTrans->m_pSlotRailNear)
    {
        return false;
    }

    if (!psmTrans->IsWaitTask()
        || !psmUnload->IsWaitTask())
    {
        return false;
    }

    //检查资源是否可用
    //注意此时如果上下料在清洗区，是不能工作的
    if (!ResManager().CanAcquire(SM_TRANS, kResTransfer | kResCheckBox
        | kAreaClean | kResRailNear))
    {
        return false;
    }

    if (pSlot->bCutFinished && pSlot->bCheckCutFinished)
    {
        //TODO:这里可以尝试kTransCheckBoxToCass
        //为了处理全部下料,这里先转到railnear
        AddMsgToState(SM_TRANS, CProcess_Trans::kTransCheckBoxToRailNear,
                      kResTransfer | kResCheckBox | kAreaClean | kResRailNear);
        return true;
    }
    else if (pSlot->bCheckCoatFinished && !pSlot->bCutFinished)
    {
        AddMsgToState(SM_TRANS, CProcess_Trans::kTransCheckBoxToRailNear,
                      kResTransfer | kResCheckBox | kAreaClean | kResRailNear);
        return true;
    }

    return false;
}

bool VstAutoSchedular::ProcessCupboardManualCheck()
{
    CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS,
                                               SM_TRANS, CProcess_Trans);

    CASSSLOT* pSlot = processTrans->m_pSlotCheckBox;
    if (!pSlot)
    {
        return false;
    }

    VSMT_Base* psmTrans = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_TRANS));
    VSMT_Base* psmUnload = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTUnload));
    VSMT_Base* psmLoad = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTLoad));

    if (!psmTrans->IsWaitTask()
        || !psmLoad->IsWaitTask()
        || !psmUnload->IsWaitTask())
    {
        return true;
    }

    if (pSlot->CheckStatus == CHECKCUTING)
    {
        //暂停等待检查
        m_pParent->pushfront_Msg(VarMsg_Pause_ID, QObject::trUtf8("Pause for check wafer cutting."));
        psmLoad->pushfront_Msg(VarMsg_Pause_ID, QObject::trUtf8("Pause for check wafer cutting."));
        psmUnload->pushfront_Msg(VarMsg_Pause_ID, QObject::trUtf8("Pause for check wafer cutting."));
        psmTrans->pushfront_Msg(VarMsg_Pause_ID, QObject::trUtf8("Pause for check wafer cutting."));
        g_SecsManager.SendEvent(EVENT_JobPaused);
        g_SecsManager.SendEvent(EVENT_CutingCheckStarted);

        m_gSystem.m_SysMsg.SetMsg(QObject::trUtf8("Please check cuting quality on the cupboard."));

        return true;
    }
    if (pSlot->CheckStatus == CHECKCOATING)
    {
        //通知暂停
        m_pParent->pushfront_Msg(VarMsg_Pause_ID, QObject::trUtf8("Pause for check wafer coating."));
        psmLoad->pushfront_Msg(VarMsg_Pause_ID, QObject::trUtf8("Pause for check wafer coating."));
        psmUnload->pushfront_Msg(VarMsg_Pause_ID, QObject::trUtf8("Pause for check wafer coating."));
        psmTrans->pushfront_Msg(VarMsg_Pause_ID, QObject::trUtf8("Pause for check wafer coating."));

        m_gSystem.m_SysMsg.SetMsg(QObject::trUtf8("Please check coating quality on the cupboard."));

        g_SecsManager.SendEvent(EVENT_JobPaused);
        g_SecsManager.SendEvent(EVENT_CoatingCheckStarted);

        return true;
    }

    return false;
}

bool VstAutoSchedular::ProcessClean()
{
    CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS,
                                               SM_TRANS, CProcess_Trans);

    CASSSLOT* pSlot = processTrans->m_pSlotClean;
    if (!pSlot)
    {
        return false;
    }

    VSMT_Base* psmTrans = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_TRANS));
    VSMT_Base* psmUnload = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTUnload));
    VSMT_Base* psmLoad = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTLoad));
    VSMT_Base* psmMain = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_MAIN));
    VSMT_Base* psmClean = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_CLEAN));
    VSMT_Base* psmCoat = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_COAT));

    if (pSlot->bCleanFinished)
    {

        if (processTrans->m_pSlotRailNear)
        {
            return false;
        }

        //如果有需要检查的，暂时先不拉过去
        if (processTrans->m_pSlotCheckBox)
        {
            return false;
        }

        if (!psmTrans->IsWaitTask()
            || !psmUnload->IsWaitTask()
            || !psmClean->IsWaitTask())
        {
            return false;
        }

        //检查资源是否可用
        //注意此时如果上下料在清洗区，是不能工作的
        if (!ResManager().CanAcquire(SM_TRANS, kResTransfer | kResClean
            | kAreaClean | kResRailNear | kResDoorOpen))
        {
            return false;
        }

        //TODO: 将清洗平台拉到轨道上即可
        AddMsgToState(SM_TRANS, CProcess_Trans::kTransCleanToRailNear,
                      kResTransfer | kResClean | kAreaClean | kResRailNear | kResDoorOpen);
        return true;
    }
    else
    {
        //未清洗，执行清洗操作
        if (!psmClean->IsWaitTask())
        {
            return false;
        }

        if (!ResManager().CanAcquire(SM_CLEAN, kResClean))
        {
            return false;
        }

        AddMsgToState(SM_CLEAN, VarMsg_Auto_StartClean, kResClean);
        return true;
    }
    //后续会由轨道调度
    return false;
}

bool VstAutoSchedular::ProcessCoat()
{
    CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS,
                                               SM_TRANS, CProcess_Trans);

    CASSSLOT* pSlot = processTrans->m_pSlotCoat;
    if (!pSlot)
    {
        return false;
    }

    VSMT_Base* psmTrans = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_TRANS));
    VSMT_Base* psmUnload = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTUnload));
    VSMT_Base* psmLoad = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTLoad));
    VSMT_Base* psmMain = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_MAIN));
    VSMT_Base* psmClean = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_CLEAN));
    VSMT_Base* psmCoat = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_COAT));
    if (pSlot->bCoatFinished)
    {
        if (processTrans->m_pSlotRailFar)
        {
            return false;
        }

        if (!psmTrans->IsWaitTask()
            || !psmLoad->IsWaitTask()
            || !psmCoat->IsWaitTask())
        {
            return false;
        }

        //检查资源是否可用
        //注意此时如果上下料在清洗区，是不能工作的
        if (!ResManager().CanAcquire(SM_TRANS, kResTransfer | kResCoat
            | kAreaCoat | kResRailFar | kResDoorOpen))
        {
            return false;
        }

        //TODO: 将涂覆平台拉到轨道上即可
        AddMsgToState(SM_TRANS, CProcess_Trans::kTransCoatToRailFar,
                      kResTransfer | kResCoat | kAreaCoat | kResRailFar | kResDoorOpen);


        return true;
    }
    else
    {
        //未涂覆，执行清洗操作
        if (!psmCoat->IsWaitTask())
        {
            return false;
        }

        if (!ResManager().CanAcquire(SM_COAT, kResCoat))
        {
            return false;
        }

        AddMsgToState(SM_COAT, VarMsg_Auto_StartCoat, kResCoat, "Auto Start Coat");
        return true;
    }

    //后续会由轨道调度
    return false;
}

bool VstAutoSchedular::ProcessCoatOneRail()
{
    CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS,
                                               SM_TRANS, CProcess_Trans);

    CASSSLOT* pSlot = processTrans->m_pSlotCoat;
    if (!pSlot)
    {
        return false;
    }

    VSMT_Base* psmTrans = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_TRANS));
    VSMT_Base* psmUnload = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTUnload));
    VSMT_Base* psmLoad = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTLoad));
    VSMT_Base* psmMain = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_MAIN));
    VSMT_Base* psmClean = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_CLEAN));
    VSMT_Base* psmCoat = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_COAT));
    if (pSlot->bCoatFinished)
    {
        if (processTrans->m_pSlotRailNear)
        {
            return false;
        }

        if (processTrans->m_pSlotWT)
        {
            return false;
        }

        if (processTrans->m_pSlotUnLoad)
        {
            return false;
        }

        if (!psmTrans->IsWaitTask()
            || !psmLoad->IsWaitTask()
            || !psmCoat->IsWaitTask())
        {
            return false;
        }

        //检查资源是否可用
        //注意此时如果上下料在清洗区，是不能工作的
        if (!ResManager().CanAcquire(SM_TRANS, kAreaCoat | kAreaClean | kResTransfer
            | kResCoat | kResRailFar | kResRailNear | kResDoorOpen))
        {
            return false;
        }

        //TODO: 将涂覆平台拉到轨道上即可
        AddMsgToState(SM_TRANS, CProcess_Trans::kTransCoatToRailNear,
                      kAreaCoat | kAreaClean | kResTransfer | kResCoat | kResRailFar | kResRailNear | kResDoorOpen);
        return true;
    }
    else
    {
        //未清洗，执行涂覆操作
        if (!psmCoat->IsWaitTask())
        {
            return false;
        }

        if (!ResManager().CanAcquire(SM_COAT, kResCoat))
        {
            return false;
        }

        MqDebug() << "Start Coating";
        AddMsgToState(SM_COAT, VarMsg_Auto_StartCoat, kResCoat, "Auto Start Coat");
        return true;
    }

    //后续会由轨道调度
    return false;
}

bool VstAutoSchedular::ProcessWorktable()
{
    CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS,
                                               SM_TRANS, CProcess_Trans);

    CASSSLOT* pSlot = processTrans->m_pSlotWT;
    if (!pSlot)
    {
        return false;
    }

    VSMT_Base* psmTrans = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_TRANS));
    VSMT_Base* psmUnload = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTUnload));
    VSMT_Base* psmLoad = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTLoad));
    VSMT_Base* psmMain = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_MAIN));
    VSMT_Base* psmClean = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_CLEAN));
    VSMT_Base* psmCoat = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_COAT));

    if (pSlot->bCutFinished)
    {
        if (processTrans->m_pSlotUnLoad
            || processTrans->m_pSlotRailNear
            || processTrans->m_pSlotClean)
        {
            return false;
        }

        if (!psmUnload->IsWaitTask()
            || !psmMain->IsWaitTask())
        {
            return false;
        }

        //检查资源是否可用
        //注意此时如果上下料在清洗区，是不能工作的
        if (!ResManager().CanAcquire(SM_WTUnload, kResUnload | kResWt
            | kAreaClean | kResRailNear))
        {
            return false;
        }

        //TODO: 将加工平台拉到轨道上即可
        AddMsgToState(SM_WTUnload, CProcess_Trans::kTransWorktableToRailNear,
                      kResUnload | kResWt | kAreaClean | kResRailNear,
                      processTrans->GetMsgName(CProcess_Trans::kTransWorktableToRailNear));
        return true;
    }
    else
    {
        //未切割，执行切割操作
        if (!psmMain->IsWaitTask())
        {
            return false;
        }

        if (!ResManager().CanAcquire(SM_MAIN, kResWt))
        {
            return false;
        }

        AddMsgToState(SM_MAIN, VarMsg_Auto_StartCut, kResWt, "Auto Start Cut");
        return true;
    }
    return false;
}

bool VstAutoSchedular::ProcessUnload()
{
    return false;
}

bool VstAutoSchedular::ProcessLoad()
{
    return false;
}

bool VstAutoSchedular::ProcessCasste()
{

    CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
    bool bIsCutFinished = pCass->IsCassCutFinished();
    if (bIsCutFinished)
    {
        if (!ResManager().CanAcquire(SM_TRANS, kResCassete | kResTransfer | kResRailNear))
        {
            return false;
        }

        {
            VSMT_Base* psmTrans = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_TRANS));
            if (!psmTrans->IsWaitTask())
            {
                return false;
            }
        }

        CMWorkTableDriver* pWorkTableDriver = GET_CARD(WORKTABLE_DRIVER,
                                                       CMWorkTableDriver);

        pWorkTableDriver->ManualLoadPos(WORKTABLE);

        CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS, SM_TRANS, CProcess_Trans);
        processTrans->MoveHGrabWait();

        CProcess_Scan* pCass = GET_PROCESS(PROCESS_SCAN, SM_TRANS,
                                           CProcess_Scan);
        pCass->CassUp(CASSETTE);

        m_gSystem.EvtLog(QString::fromUtf8("FAE"),
                         QObject::trUtf8("Cassette Cut Finished"));
        //结束计时
        m_gSystem.m_totalWorkTime.StopTime();
        m_gSystem.m_fullAutoTime.StopTime();
        m_gSystem.m_totalWorkHour += m_gSystem.m_totalWorkTime.GetTime() / 3600;
        m_gSystem.m_totalWorkTime.ClearTime();

        int maxCycleCount = m_gSystem.m_Variants.get_VData(Var_MaxCycle_Count)->toInt();
        if (m_gSystem.m_bEnableCycle
            && (maxCycleCount <= 0 || (maxCycleCount > 0 && m_gSystem.m_iTotalCuttedWafer < maxCycleCount)))
        {
            clear_Msg();
            pushback_Msg(VarMsg_StartAuto_ID,
                         QObject::trUtf8("Restart auto cycle"));
            LOG_INFO("Restart auto cycle");
        }
        else
        {
            g_SecsManager.SendEvent(EVENT_JobComplete);
            clear_Msg();
            m_gSystem.publish_msg(V_Msg(VarMsg_Stop_ID,
                                  QObject::trUtf8("Cut Finished,Stop All")));
            m_gSystem.m_SysMsg.SetMsg(QObject::trUtf8("Cassette Cut Finished"));
            LOG_INFO("All Job Finished");
        }
        return true;
    }


    VSMT_Base* psmTrans = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_TRANS));
    VSMT_Base* psmUnload = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTUnload));
    VSMT_Base* psmLoad = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTLoad));
    VSMT_Base* psmMain = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_MAIN));
    VSMT_Base* psmClean = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_CLEAN));
    VSMT_Base* psmCoat = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_COAT));

    if (!psmTrans->IsWaitTask())
    {
        return false;
    }
    else
    {
        //MqDebug() << SM_TRANS << " is not wait task";
    }

    CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS,
                                               SM_TRANS, CProcess_Trans);

    if (processTrans->m_pSlotRailNear)
    {
        return false;
    }

    //远端有未检查涂覆的晶圆
    if (processTrans->m_pSlotRailFar)
    {
        return false;
    }

    //涂覆台有未检查的晶圆
    if (processTrans->m_pSlotCoat)
    {
        return false;
    }

    //检查盒有晶圆
    if (processTrans->m_pSlotCheckBox)
    {
        return false;
    }

    //if (processTrans->m_pSlotUnLoad) {
    //    return false;
    //}

    //if (processTrans->m_pSlotLoad) {
    //    return false;
    //}

    if (!ResManager().CanAcquire(SM_TRANS, kResCassete | kResTransfer | kAreaClean | kResRailNear))
    {
        return false;
    }

    //料盒往轨道拉晶圆
    //TODO:
    if (pCass->GetFirstUnCutWafer())
    {
        MqDebug() << "((((((AddMsgToState" << "TransCassToRailNear" << this->QueueSize();
        psmTrans->IsWaitTask();

        AddMsgToState(SM_TRANS, CProcess_Trans::kTransCassToRailNear,
                      kResCassete | kResTransfer | kAreaClean | kResRailNear,
                      processTrans->GetMsgName(CProcess_Trans::kTransCassToRailNear));
        return true;
    }

    return false;
}

bool VstAutoSchedular::ProcessCassteOneRail()
{
    CCassette* pCass = GET_CHDIRECT(CASSETTE, CCassette);
    bool bIsCutFinished = pCass->IsCassCutFinished();
    if (bIsCutFinished)
    {
        CMWorkTableDriver* pWorkTableDriver = GET_CARD(WORKTABLE_DRIVER,
                                                       CMWorkTableDriver);

        pWorkTableDriver->ManualLoadPos(WORKTABLE);

        CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS, SM_TRANS, CProcess_Trans);
        processTrans->MoveHGrabWait();

        CProcess_Scan* pCass = GET_PROCESS(PROCESS_SCAN, SM_TRANS,
                                           CProcess_Scan);
        pCass->CassUp(CASSETTE);

        m_gSystem.EvtLog(QString::fromUtf8("FAE"),
                         QObject::trUtf8("Cassette Cut Finished"));
        //结束计时
        m_gSystem.m_totalWorkTime.StopTime();
        m_gSystem.m_fullAutoTime.StopTime();
        m_gSystem.m_totalWorkHour += m_gSystem.m_totalWorkTime.GetTime() / 3600;
        m_gSystem.m_totalWorkTime.ClearTime();

        int maxCycleCount = m_gSystem.m_Variants.get_VData(Var_MaxCycle_Count)->toInt();
        if (m_gSystem.m_bEnableCycle
            && (maxCycleCount <= 0 || (maxCycleCount > 0 && m_gSystem.m_iTotalCuttedWafer < maxCycleCount)))
        {
            clear_Msg();
            pushback_Msg(VarMsg_StartAuto_ID,
                         QObject::trUtf8("Restart auto cycle"));
        }
        else
        {
            g_SecsManager.SendEvent(EVENT_JobComplete);
            m_gSystem.publish_msg(V_Msg(VarMsg_Stop_ID,
                                  QObject::trUtf8("Cut Finished,Stop All")));
            m_gSystem.m_SysMsg.SetMsg(QObject::trUtf8("Cassette Cut Finished"));
        }
        return true;
    }


    VSMT_Base* psmTrans = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_TRANS));
    VSMT_Base* psmUnload = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTUnload));
    VSMT_Base* psmLoad = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_WTLoad));
    VSMT_Base* psmMain = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_MAIN));
    VSMT_Base* psmClean = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_CLEAN));
    VSMT_Base* psmCoat = static_cast<VSMT_Base*>(m_gSystem.FindSM(SM_COAT));

    if (!psmTrans->IsWaitTask())
    {
        return false;
    }
    else
    {
        //MqDebug() << SM_TRANS << " is not wait task";
    }

    CProcess_Trans* processTrans = GET_PROCESS(PROCESS_TRANS,
                                               SM_TRANS, CProcess_Trans);

    if (processTrans->m_pSlotRailNear)
    {
        return false;
    }

    //远端有未检查涂覆的晶圆
    if (processTrans->m_pSlotRailFar)
    {
        return false;
    }

    //涂覆台有未检查的晶圆
    if (processTrans->m_pSlotCoat)
    {
        return false;
    }

    //检查盒有晶圆
    if (processTrans->m_pSlotCheckBox)
    {
        return false;
    }

    if (!ResManager().CanAcquire(SM_TRANS, kResCassete | kResTransfer | kAreaClean | kResRailNear))
    {
        return false;
    }

    //料盒往轨道拉晶圆
    //TODO:
    if (pCass->GetFirstUnCutWafer())
    {
        MqDebug() << "((((((AddMsgToState" << "TransCassToRailNear" << this->QueueSize();
        psmTrans->IsWaitTask();

        AddMsgToState(SM_TRANS, CProcess_Trans::kTransCassToRailNear,
                      kResCassete | kResTransfer | kAreaClean | kResRailNear,
                      processTrans->GetMsgName(CProcess_Trans::kTransCassToRailNear));
        return true;
    }

    return false;
}
