// PhaseCheckBuild.cpp: implementation of the CPhaseCheckBuild class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "PhaseCheckBuild.h"


//
#define T_SECT_VERSION          ( "VERSION" )
#define T_KEY_MAGIC             ( "MAGIC NUMBER" )
#define T_SECT_STATION          ( "STATION" )
#define T_KEY_STATION_NUM       ( "STATION NUMBER" )
#define T_KEY_STATION           ( "STATION" )

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CPhaseCheckBuild::CPhaseCheckBuild()
{
    ZeroMemory(&m_phaseBuf05, sizeof(m_phaseBuf05));
    ZeroMemory(&m_phaseBuf09, sizeof(m_phaseBuf09));
    m_eMagic = SP09;
}

CPhaseCheckBuild::~CPhaseCheckBuild()
{

}

BOOL CPhaseCheckBuild::LoadConfigFile()
{
    char szIniPath[MAX_PATH] = {0};
    GetModuleFileNameA(NULL, szIniPath, MAX_PATH);
    char *pPos = strrchr(szIniPath, '\\');
    if (NULL == pPos)
    {
        return FALSE;
    }
    else
    {
        *pPos = 0;
        strcat(szIniPath, "\\PhaseCheck.ini");
    }

    // Version: Magic
    char szMagic[20] = {0};
    GetPrivateProfileStringA(T_SECT_VERSION, T_KEY_MAGIC, "SP09", szMagic, sizeof(szMagic), szIniPath);
    if (0 == stricmp(szMagic, "SP09"))
    {
        // SP09
        m_eMagic = SP09;
        ZeroMemory(&m_phaseBuf09, sizeof(m_phaseBuf09));

        m_phaseBuf09.Magic      = SP09_SPPH_MAGIC_NUMBER;    
        m_phaseBuf09.StationNum = (BYTE)GetPrivateProfileIntA(T_SECT_STATION, T_KEY_STATION_NUM, 5, szIniPath);
        if (   0 == m_phaseBuf09.StationNum 
            || m_phaseBuf09.StationNum > SP09_MAX_STATION_NUM ) 
        {        
            return FALSE;
        }

        for (int i=0; i<m_phaseBuf09.StationNum; i++)
        {
            char szKey[20] = {0};
            sprintf(szKey, "%s %d", T_KEY_STATION, i+1);
        
            GetPrivateProfileStringA(T_SECT_STATION, szKey, "", m_phaseBuf09.StationName[i], SP09_MAX_STATION_NAME_LEN, szIniPath);
        }
    }
    else if (0 == stricmp(szMagic, "SP05"))
    {
        // SP05
        m_eMagic = SP05;
        ZeroMemory(&m_phaseBuf05, sizeof(m_phaseBuf05));

        m_phaseBuf05.header.Magic = SP05_SPPH_MAGIC_NUMBER;
        m_phaseBuf05.header.StationNum = (BYTE)GetPrivateProfileIntA(T_SECT_STATION, T_KEY_STATION_NUM, 5, szIniPath);
        if (   0 == m_phaseBuf05.header.StationNum 
            || m_phaseBuf05.header.StationNum > SP05_MAX_SUPPORT_STATION ) 
        {        
            return FALSE;
        }

        for (int i=0; i<m_phaseBuf05.header.StationNum; i++)
        {
            char szKey[20] = {0};
            sprintf(szKey, "%s %d", T_KEY_STATION, i+1);
        
            GetPrivateProfileStringA(T_SECT_STATION, szKey, "", m_phaseBuf05.items[i].TestStationName, SP05_TSN_LEN, szIniPath);
        }
    }
    else
    {
        // Invalid magic
        return FALSE;
    }

    return TRUE;
}

BOOL CPhaseCheckBuild::CnstPhaseInfo(const char *sn, LPBYTE lpData, int nDataLen, int *pnRetLen)
{
    if (NULL == lpData || IsBadWritePtr(lpData, nDataLen))
    {
        //
        return FALSE;
    }

    if ( !LoadConfigFile() )
    {
        //
        return FALSE;
    }

    if (SP09 == m_eMagic)
    {
        if ( nDataLen < SP09_MAX_PHASE_BUFF_SIZE )
        {
            return FALSE;
        }

        if (NULL != sn)
        {
            int nInpSnLen = lstrlenA(sn);
            memcpy(m_phaseBuf09.SN1, sn, nInpSnLen>SP09_MAX_SN_LEN?SP09_MAX_SN_LEN:nInpSnLen);
        }

        if (NULL != pnRetLen)
        {
            *pnRetLen = SP09_MAX_PHASE_BUFF_SIZE;
        }

        memcpy(lpData, &m_phaseBuf09, SP09_MAX_PHASE_BUFF_SIZE);
    }
    else
    {
        if ( nDataLen < SP05_MAX_PHASE_BUFF_SIZE )
        {
            return FALSE;
        }

        if (NULL != sn)
        {
            int nInpSnLen = lstrlenA(sn);
            memcpy(m_phaseBuf05.header.SN, sn, nInpSnLen>SP05_SN_LEN?SP05_SN_LEN:nInpSnLen);
        }

        if (NULL != pnRetLen)
        {
            *pnRetLen = SP05_MAX_PHASE_BUFF_SIZE;
        }

        memcpy(lpData, &m_phaseBuf05, SP05_MAX_PHASE_BUFF_SIZE);
    }
    

    return TRUE;
}

BOOL CPhaseCheckBuild::CnstPhaseInfo(const char *sn1, const char *sn2, LPBYTE lpData, int nDataLen, int *pnRetLen)
{
    if (NULL == lpData || IsBadWritePtr(lpData, nDataLen))
    {
        //
        return FALSE;
    }

    if ( !LoadConfigFile() )
    {
        //
        return FALSE;
    }

    if (SP09 == m_eMagic)
    {
        if ( nDataLen < SP09_MAX_PHASE_BUFF_SIZE )
        {
            return FALSE;
        }

        if (NULL != sn1)
        {
            int nInpSnLen = lstrlenA(sn1);
            memcpy(m_phaseBuf09.SN1, sn1, nInpSnLen>SP09_MAX_SN_LEN?SP09_MAX_SN_LEN:nInpSnLen);
        }

        if (NULL != sn2)
        {
            int nInpSnLen = lstrlenA(sn2);
            memcpy(m_phaseBuf09.SN2, sn2, nInpSnLen>SP09_MAX_SN_LEN?SP09_MAX_SN_LEN:nInpSnLen);
        }

        if (NULL != pnRetLen)
        {
            *pnRetLen = SP09_MAX_PHASE_BUFF_SIZE;
        }


        memcpy(lpData, &m_phaseBuf09, SP09_MAX_PHASE_BUFF_SIZE);
    }
    else
    {
        if ( nDataLen < SP05_MAX_PHASE_BUFF_SIZE )
        {
            return FALSE;
        }

        if (NULL != sn1)
        {
            int nInpSnLen = lstrlenA(sn1);
            memcpy(m_phaseBuf05.header.SN,  sn1,  nInpSnLen>SP05_SN_LEN?SP05_SN_LEN:nInpSnLen);
        }

        if (NULL != sn2)
        {
            int nInpSnLen = lstrlenA(sn2);
            memcpy(m_phaseBuf05.header.SN2, sn2,  nInpSnLen>SP05_SN_LEN?SP05_SN_LEN:nInpSnLen);
        }

        if (NULL != pnRetLen)
        {
            *pnRetLen = SP05_MAX_PHASE_BUFF_SIZE;
        }

        
        memcpy(lpData, &m_phaseBuf05, SP05_MAX_PHASE_BUFF_SIZE);
    }
    

    return TRUE;
}

BOOL CPhaseCheckBuild::Cnst8KBuffer(const char *sn/*IN*/, LPBYTE lpData/*OUT*/, int nDataLen)
{
    if (NULL == lpData || nDataLen < MAX_PRODUCTIONINFO_SIZE || IsBadWritePtr(lpData, nDataLen))
    {
        //
        return FALSE;
    }
  
    memset(lpData, 0xFF, nDataLen);

    if ( !CnstPhaseInfo(sn, lpData, nDataLen, NULL) )
    {
        //
        return FALSE;
    }
    
    //  Xiaoping: 严格判断DOWNLOAD站位名称，如果有DOWNLOAD站，则设置PASS[[[ 
    if (SP09 == m_eMagic)
    {
        for (int nIndex=0; nIndex<m_phaseBuf09.StationNum; nIndex++)
        {
            if (0 == stricmp(m_phaseBuf09.StationName[nIndex], "DOWNLOAD"))
            {
                m_phaseBuf09.iItem |= (1 << nIndex);
                break;
            }
        }
    }
    else
    {
        for (int nIndex=0; nIndex<m_phaseBuf05.header.StationNum; nIndex++)
        {
            if (0 == stricmp(m_phaseBuf05.items[nIndex].TestStationName, "DOWNLOAD"))
            {
                memcpy(m_phaseBuf05.items[nIndex].TestState, "PASS", 4);
                break;
            }
        }
    }
    //  ]]]


    return TRUE;
}

BOOL CPhaseCheckBuild::FindSnFrom8K(const BYTE *lpData, int nDataLen, BYTE *sn, int nSnLen)
{
#define  CONVERT_INT(Src,Dst)   {\
                                 (Dst)  = MAKELONG(MAKEWORD(HIBYTE(HIWORD(Src)),LOBYTE(HIWORD(Src))),\
                                                   MAKEWORD(HIBYTE(LOWORD(Src)),LOBYTE(LOWORD(Src))));\
                                }


    if (   NULL == lpData 
        || nDataLen < MAX_PRODUCTIONINFO_SIZE
        || IsBadReadPtr(lpData, nDataLen)
       )
    {
        //
        return FALSE;
    }

    if (SP05_SPPH_MAGIC_NUMBER == *((unsigned long *)lpData))
	{			
		LPSP05_PHASE_CHECK_T pPhaseCheckData = (LPSP05_PHASE_CHECK_T)lpData;
		memcpy(sn, pPhaseCheckData->header.SN, nSnLen);

        return TRUE;
	}
	else if (SP09_SPPH_MAGIC_NUMBER == *((unsigned long *)lpData))
	{
    /*********************************************************************** 
        Lookup the latest data block
        block size must be equal or multiple than SP09_MAX_PHASE_BUFF_SIZE
      
    **********************************************************************/
    
        const int BLOCK_SIZE  = SP09_MAX_PHASE_BUFF_SIZE;
        int nTotalBlockNum = MAX_PRODUCTIONINFO_SIZE/BLOCK_SIZE;
        LPBYTE lpBuff = (LPBYTE)(lpData+MAX_PRODUCTIONINFO_SIZE-BLOCK_SIZE);
        for (int nIndex=0; nIndex<nTotalBlockNum-1; nIndex++)
        {
            
            if (SP09_SPPH_MAGIC_NUMBER == *((unsigned long *)lpBuff))
            {
                // Find the last data block
                break;
            }
            
            lpBuff -= BLOCK_SIZE;
        }
        
        LPSP09_PHASE_CHECK_T lpPhaseInfo = (LPSP09_PHASE_CHECK_T)(lpBuff);
        memcpy(sn, lpPhaseInfo->SN1, nSnLen);
        
        return TRUE;
    }
    


#if 0
		DWORD dwIndex = *((DWORD*)(lpData+(MAX_PRODUCTIONINFO_SIZE-4)));		
		CONVERT_INT(dwIndex, dwIndex);

		int nIndex = 0;

		/************************************************************************/
		/*  if dwIndex == 0xFFFFFFFF, nIndex = 0
		/*  if dwIndex == 0xFFFFFFFE, nIndex = 1                                */
		/************************************************************************/
	
		if (dwIndex != 0xFFFFFFFF)
		{
			for(int i = 0; i< 32; i++)
			{
				nIndex = ((dwIndex & (1<<(31-i)) )>> (31-i));
				if(nIndex == 0)
				{
					nIndex = (32-i);
					break;
				}
			}
		}
		// the range of  nIndex is [0,30], the last one 31 is not used.
		if (nIndex >= 0 && nIndex <= 30)
		{
			LPSP09_PHASE_CHECK_T pPhaseCheckData = (LPSP09_PHASE_CHECK_T)lpData;
			pPhaseCheckData += nIndex;
			memcpy(sn, pPhaseCheckData->SN1, nSnLen);

            return TRUE;
		}

	}
    else
    {
        return FALSE;
    }
#endif

    return FALSE;
}