#include "vst_work_schedular.h"
#include "msg_def.h"
#include "cmallsystem.h"
#include "logic_eap.h"
#include "cprocess_trans.h"
#define pStateInstance() static_cast<VST_Work_Schedular*>(m_pNextState)
VST_Work_Schedular::VST_Work_Schedular(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_Schedular::do_Msg(const V_Msg& msg)
{
    switch (msg.m_iID) {
        case VarMsg_Schedular_Prepare:
            //扫描料盒
            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_Dispatch_Msg,
                                 QObject::trUtf8("Scan Cass"),
                                 QVariantList() << SM_TRANS
                                 << CProcess_Trans::kTransScanCass << QObject::trUtf8("Scan Cass")
                                 << false
                                 << uint(kResCassete | kResTransfer)
                                 << uint(kVsmTransfer));
                pStateInstance()->LoadMsgProcess();
            }
            m_pParent->SetState(m_pNextState);
            //切割平台初始化操作

            break;
        case VarMsg_Schedular_Dispatch_Msg:
        {
            
            if (!m_pNextState) {
                m_pNextState = new VST_Work_Schedular(VarState_Wait_Schedular,
                                                      QObject::trUtf8("Work Schedular"), m_pParent, this, 0);

                int vsmId = msg.m_vlInput[0].toInt();
                uint nAcqResId = msg.m_vlInput[4].toUInt();
                uint releaseId = msg.m_vlInput[5].toUInt();
                int transMsgId = msg.m_vlInput[1].toInt();
                MqDebug() << "VarMsg_Schedular_Dispatch_Msg" << vsmId;

                //请求锁定资源
                pStateInstance()->m_VarMsgProcess.
                    pushback_Msg(VarMsg_AcquireResouce,
                                 QObject::trUtf8("Acquire Resource"),
                                 QVariantList() << vsmId << releaseId);

                V_Msg newMsg = msg;
                newMsg.m_iID = VarMsg_Schedular_AddTransMsg;
                pStateInstance()->m_VarMsgProcess.pushback_Msg(newMsg);

                //检查被调度的资源是否调度成功
                pStateInstance()->m_VarMsgProcess.
                    pushback_Msg(VarMsg_CheckResouceLocked,
                                 QObject::trUtf8("Check Acquire Resource"),
                                 QVariantList() << vsmId << releaseId << transMsgId);

                pStateInstance()->LoadMsgProcess();

                //pStateInstance()->m_waitTime.ClearTime();
                pStateInstance()->m_waitTime.Restart();
            }
            m_pParent->SetState(m_pNextState);
            break;
        }
        case VarMsg_Schedular_AddTransMsg:
        {
            int vsmId = msg.m_vlInput[0].toInt();
            int transMsgId = msg.m_vlInput[1].toInt();
            QString sName = msg.m_vlInput[2].toString();
            bool bFront = msg.m_vlInput[3].toBool();
            uint nAcqResId = msg.m_vlInput[4].toUInt();
            uint nResId = msg.m_vlInput[5].toUInt();
            if (!AddMsgToState(vsmId, nResId, nAcqResId, transMsgId, sName, bFront)) {
                pushfront_Msg(msg);
            }
            
            break;
        }
        case VarMsg_Schedular_AddStateMsg:
        {
            V_Msg newMsg = msg;
            newMsg.m_iID = msg.m_vlInput[0].toInt();;
            newMsg.m_vlInput.pop_front();
            int vsmId = newMsg.m_vlInput[0].toInt();
            AddMsgToSM(vsmId, msg, false);
            break;
        }
        case VarMsg_CheckResouceLocked:
        {
            //检查调度是否成功
            m_waitTime.StartTime();
            int vsmId = msg.m_vlInput[0].toInt();
            uint resId = msg.m_vlInput[1].toUInt();
            double time = m_waitTime.GetTime();
            if (time > 5) {
                m_waitTime.StopTime();
                MQT_THROW_CODESTR(ALARM_RESERVED, QObject::tr("wait schedular timeout"));
            }

            //未释放
            if (ResManager().CanAcquire(vsmId, resId)) {
                MqDebug() << "VarMsg_CheckResouceLocked  sucess";

                int transId = msg.m_vlInput[2].toInt();
                if (transId == CProcess_Trans::kTransCassToRailNear) {
                    int x = 0;
                }

                VSM_Thread* psmTrans = m_gSystem.FindSM(vsmId);
                if (!psmTrans->IsWaitTask()) {
                    MqDebug() << vsmId << " is wait task";
                }
            } else {
                pushfront_Msg(msg);
            }

            break;
        }
        default:
            break;
    }

    VST_Work_Base::do_Msg(msg);
}


bool VST_Work_Schedular::AddMsgToState(int iSMId, uint nResId, uint nAcqResId, int iTransMsgID, const QString &msgName, bool bfront/*=false*/)
{
    VSM_Thread* pSM = m_gSystem.FindSM(iSMId);
    
    if (pSM->IsWaitTask()) {
        QMutexLocker l(&pSM->m_SMMutex);
        pSM->pushBack_Msg_toState(pSM->m_pState_Wait, 
                                  V_Msg(VarMsg_ReleaseSchedularAndLockRes, "Release Msg", 
                                  QVariantList() << iSMId << nResId << nAcqResId));
        if (iSMId == SM_MAIN || iSMId == SM_CLEAN || iSMId == SM_COAT) {
            //pSM->m_pState_Wait->pushback_Msg(iTransMsgID, msgName);
            pSM->pushBack_Msg_toState(pSM->m_pState_Wait, V_Msg(iTransMsgID, msgName));
        }
        else {
            //pSM->m_pState_Wait->pushback_Msg(VarMsg_AddMsg, "AddMsg", QVariantList() << iTransMsgID << msgName);
            pSM->pushBack_Msg_toState(pSM->m_pState_Wait, V_Msg(VarMsg_AddMsg, "AddMsg", QVariantList() << iTransMsgID << msgName));
        }
    } else {
        if (pSM->IsWork()) {

        }
        return false;
    }
    return true;

}

void VST_Work_Schedular::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;
    }
}