#include "ccassette.h"
#include "logic.h"

QDataStream &operator<<(QDataStream &out,const CASSSLOT& param)
{
	out<<param.WPstatus;
	out<<param.index;
	out<<param.bEnableCut;
	out<<param.bAbort;
	out<<param.bCanAbort;
	out<<(int)param.CheckStatus;
	out<<param.bNeedCheckCoat;
	out<<param.bNeedCheckCut;
	out<<param.bIsFirst;

	out << param.bNeedCheckCoat;
	out << param.bNeedCheckCut;
	out << param.bCoatFinished;
	out << param.bCleanFinished;

	out << param.bNeedRelocation;
	out << param.bHasWater;
	
	out<<param.WaferID;
	out<<param.BeginDate;
	out<<param.EndDate;
	return out;
}
QDataStream &operator>>(QDataStream &in, CASSSLOT& param)
{
	in>>param.WPstatus;
	in>>param.index;
	in>>param.bEnableCut;
	in>>param.bAbort;
	in>>param.bCanAbort;
	int checkStatus;
	in>>checkStatus; param.CheckStatus = (SLOT_CHECK_STATUS)checkStatus;
	
	in>>param.bNeedCheckCoat;
	in>>param.bNeedCheckCut;
	in>>param.bIsFirst;

    in >> param.bNeedCheckCoat;
    in >> param.bNeedCheckCut;
    in >> param.bCoatFinished;
    in >> param.bCleanFinished;

	in >> param.bNeedRelocation;
    in >> param.bHasWater;

	in>>param.WaferID;
	in>>param.BeginDate;
	in>>param.EndDate;
	return in;
}

CCassette::CCassette(const QString &name, int32_t id)
    :CChannel(name,id)
{
    m_Variants.add_Variant(Var_Cass_Slot_Count,
                           QObject::trUtf8("Slot_Count"),int(25),false,
                           Variant::TOXML);


    for(int i=0;i<MAX_SLOT;i++)
    {
        vslots[i].index=i;
    }
    ch_wp_status <<
QObject::tr("UnScanned")<<
QObject::tr("NoWP")<<
QObject::tr("unCut")<<
QObject::tr("MALPOSED")<<
QObject::tr("OVERLAPPED")<<
QObject::tr("SCANFAILED")<<
QObject::tr("Grab")<<
QObject::tr("to Coat")<<
QObject::tr("Coating")<<
QObject::tr("Coat Finish")<<
QObject::tr("to Cut")<<
QObject::tr("Cutting")<<
QObject::tr("Cutt Finish")<<
QObject::tr("to Clean")<<
QObject::tr("Cleaning")<<
QObject::tr("Clean Finish")<<
QObject::tr("to UnLoad")<<
QObject::tr("Cutted")<<
QObject::tr("Abort")<<
QObject::tr("Checking")<<
QObject::tr("Checked");
}

CCassette::~CCassette()
{

}


void CCassette::ResetSlots()
{
    for(int i=0;i<MAX_SLOT;i++)
    {
        vslots[i].Reset();
		vslots[i].WaferID = "";
	}

	m_bFirstFinished = true;
}


CASSSLOT *CCassette::GetFirstUnCutWafer()
{
    int slotcount=m_Variants.get_VData(Var_Cass_Slot_Count)->toInt();
    Q_ASSERT(slotcount>=0&&slotcount<=MAX_SLOT);

	//HACK:Cycle时,如果完成后结束,设置此标志
	if(m_gSystem.m_bStopAfterFinish){
		return 0;
	}
    for (int i=0;i<slotcount;i++)
    {
        if (vslots[i].WPstatus==WPUNCUT&&vslots[i].bEnableCut)
        {
            return &(vslots[i]);
        }
    }
    return 0;
}

void CCassette::SetNextUnCutWaferChecked()
{
	
	int slotcount=m_Variants.get_VData(Var_Cass_Slot_Count)->toInt();
	Q_ASSERT(slotcount>=0&&slotcount<=MAX_SLOT);

	for (int i=0;i<slotcount;i++)
	{
		if (vslots[i].WPstatus==WPUNCUT&&vslots[i].bEnableCut)
		{
			//找到料盒最近一片没切割的
			//LOG(INFO)<<"SetNextUnCutWaferChecked Index:%1" << i+1 << "Wafer ID " << vslots[i].WaferID.toStdString().c_str();
			//m_gSystem.AddProductInfo(vslots[i].WaferID, QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss") + " Reset to coat quality checked", true);
			vslots[i].bNeedCheckCoat = true;
			vslots[i].bNeedCheckCut = true;
			break; 
			
		}
	}
	return;
}

CASSSLOT *CCassette::GetFirstWafer()
{
    int slotcount=m_Variants.get_VData(Var_Cass_Slot_Count)->toInt();
    Q_ASSERT(slotcount>=0&&slotcount<=MAX_SLOT);

    for (int i=0;i<slotcount;i++)
    {
        if (vslots[i].WPstatus!=NOWP&&vslots[i].bEnableCut)
        {
            return &(vslots[i]);
        }
    }
    return 0;
}

CASSSLOT* CCassette::GetCheckBoxWafer()
{
	return &m_CheckBoxWafer;
}

int CCassette::GetCassWaferNum()
{
    int slotcount=m_Variants.get_VData(Var_Cass_Slot_Count)->toInt();
    Q_ASSERT(slotcount>=0&&slotcount<=MAX_SLOT);
    int icount=0;
    for (int i=0;i<slotcount;i++)
    {
        if (vslots[i].WPstatus )
        {
            icount++;
        }
    }
    return icount;
}

BOOL CCassette::IsCassCutFinished()
{
    int slotcount=m_Variants.get_VData(Var_Cass_Slot_Count)->toInt();
    Q_ASSERT(slotcount>=0&&slotcount<=MAX_SLOT);
    for (int i=0;i<slotcount;i++)
    {
        if(vslots[i].WPstatus!=NOWP&&vslots[i].bEnableCut)
        {
            if (vslots[i].WPstatus!=WPCUTTED&&
                    vslots[i].WPstatus!=WPABORT
                    )
            {
				//HACK:Cycle时,如果设置完成后结束标志，则剩下未处理的晶圆不再处理
				if(m_gSystem.m_bStopAfterFinish 
					&& vslots[i].WPstatus==WPUNCUT)
				{
					continue;
				}

                return false;
            }
        }
    }
    return true;
}

BOOL CCassette::IsCassHasUnCutCell()
{
    int slotcount=m_Variants.get_VData(Var_Cass_Slot_Count)->toInt();
    Q_ASSERT(slotcount>=0&&slotcount<=MAX_SLOT);
    for (int i=0;i<slotcount;i++)
    {
        if(vslots[i].WPstatus!=NOWP&&vslots[i].bEnableCut )
        {
            if (vslots[i].WPstatus==WPUNCUT
				&& vslots[i].WPstatus!=WPABORT)
            {
                return true;
            }

        }
    }
    return false;
}

bool CCassette::IsSlotFirstInCass(CASSSLOT* pSlot)
{
    int slotcount=m_Variants.get_VData(Var_Cass_Slot_Count)->toInt();
    if(!pSlot) return false;
    int i=0;
    for(i=0;i<slotcount;i++)
    {
        if(vslots[i].WPstatus!=NOWP&&vslots[i].WPstatus!=WPABORT&&vslots[i].bEnableCut )
        {
            break;
        }
    }
    return pSlot->index==i;
}

bool CCassette::IsCassEmpty()
{
    int slotcount=m_Variants.get_VData(Var_Cass_Slot_Count)->toInt();
    for(int i=0;i<slotcount;i++)
    {
        if(vslots[i].WPstatus!=NOWP&&vslots[i].WPstatus!=WPABORT)
        {
            return false;
        }
    }
    return true;
}

bool CCassette::IsFirstCheckFinished()
{
	return m_bFirstFinished;
}

void CCassette::SetFirstCheckFinished(bool bFinshed)
{
	m_bFirstFinished = bFinshed;
}

bool CCassette::WriteRecoveredData()
{
	try{
		QString filePath = m_gSystem.MakeRecoverPath("Cassete.dat");
		QFile file(filePath);
		if(!file.open(QIODevice::WriteOnly)){
            LOG_ERR(fmt::format("{} {}", "create WriteRecoveredData file failed ", filePath.toLocal8Bit().data()));
			return false;
		}

		QDataStream stream(&file);
		stream<<MAX_SLOT;
		for(int i=0;i<MAX_SLOT;i++)
		{
			stream<<vslots[i];
		}
		file.close();
		m_gSystem.LogInfo("Write Recovered data success");
		return true;
	}
	catch(std::exception ex)
	{
		LOG_ERR("create WriteRecoveredData failed ");
		return false;
	}
}

bool CCassette::ReadRecoveredData()
{
	try{
		QString filePath = m_gSystem.MakeRecoverPath("Cassete.dat");
		QFile file(filePath);
		if(!file.open(QIODevice::ReadOnly)){
			//LOG(ERROR)<<ERR_TITTLE()<<"create WriteRecoveredData file failed "<< filePath.toStdString();
            LOG_ERR("create WriteRecoveredData file failed ");
			return false;
		}

		QDataStream stream(&file);
		int size =0;
		stream>>size;
		for(int i=0;i<size;i++)
		{
			stream>>vslots[i];
		}
		file.close();
		m_gSystem.LogInfo("Read Recovered data success");

		return true;
	}catch(std::exception ex){
		LOG_ERR("ReadRecoveredData Failed");
		return false;
	}
}

bool CCassette::IsCasseteWafer(CASSSLOT* pSlot)
{
    for (int i = 0; i < MAX_SLOT; i++)
    {
		if (pSlot == &vslots[i])
		{
			return true;
		}
    }

	if (pSlot == &m_CheckBoxWafer)
	{
		return true;
	}

	return false;
}

