#include "p_apps.h"
#include "my_mgcp.h"

#define DIGITMAP_MASK_X		0x03ff
static CSHORT _cDigitMapMask[MAP_KEY_NUM] = 
{
	0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
	0x0100, 0x0200, 0x0400, 0x0800, 0x1000
};

/**********************************************************************************
****** MGCP ditmap functions ******************************************************
***********************************************************************************/
void MgcpMapAddEntry(PXCHAR pMapEntry)
{
	PXCHAR_D pCur;
	PXSHORT_D pDst;
	DCHAR i, iLen, iDotIndex;
	DSHORT iVal;

	if (Sys_iDigitMapNum >= MAP_SDRAM_NO)	return;

	iLen = 0;
	iDotIndex = 0;
	pCur = (PXCHAR)pMapEntry;
	pDst = (PXSHORT)Sdram_pDataCache;

	while (*pCur != 0)
	{
		iVal = 0;
		if (*pCur == '[')
		{
			pCur ++;
			while (*pCur != ']')
			{
				if (pCur[1] == '-')
				{
					for (i = (UCHAR)(*pCur - '0'); i <= (UCHAR)(pCur[2] - '0'); i ++)
					{
						iVal |= _cDigitMapMask[i];
					}
					pCur += 3;
				}
				else
				{
					i = p_getKeyId(pCur[0]);
					if (i != MAP_KEY_UNKNOWN)
					{
						iVal |= _cDigitMapMask[i];
					}
					pCur ++;
				}
			}
		}
		else if (*pCur == 'x' || *pCur == 'X')
		{
			iVal = DIGITMAP_MASK_X;
		}
		else if (*pCur == '.')
		{
			iDotIndex = (iLen >> 1);
			pCur ++;
			continue;
		}
		else
		{
			i = p_getKeyId(*pCur);
			if (i != MAP_KEY_UNKNOWN)
			{
				iVal = _cDigitMapMask[i];
			}
			else
			{
				pCur ++;
				continue;
			}
		}
		*pDst = iVal;
		pDst ++;
		pCur ++;
		iLen += 2;
	}

	*pDst = (USHORT)iDotIndex;
	iLen += 2;

	X_VAL(Sdram_pDataCache, SDRAM_DATA_LENGTH) = iLen;
	SdramWrite(MAP_SDRAM_HI, (UCHAR)(MAP_SDRAM_LO+Sys_iDigitMapNum), SRAM_DMA_HALF_DWORD);
	Sys_iDigitMapNum ++;
}

BOOLEAN _IsMatched(PXCHAR pEvent, UCHAR iNum)
{
	DCHAR i;
	PXSHORT_D pMap;

	pMap = (PXSHORT)Sdram_pDataCache;
	for (i = 0; i < iNum; i ++)
	{
		if ((_cDigitMapMask[pEvent[i]] & pMap[i]) == 0)
		{
			return FALSE;
		}
	}
	return TRUE;
}

BOOLEAN _IsPeriodMatched(PXCHAR pEvent, UCHAR iEventNum, PXSHORT pMap, UCHAR iMapLen)
{
	DCHAR i;

	for (i = 0; i < iMapLen; i ++)
	{
		if ((_cDigitMapMask[pEvent[i]] & pMap[i]) == 0)
		{
			return FALSE;
		}
	}
	for (i = iMapLen; i < iEventNum; i ++)
	{
		if ((_cDigitMapMask[pEvent[i]] & pMap[iMapLen-1]) == 0)
			return FALSE;
	}
	return TRUE;
}

UCHAR MgcpMatchMap(PXCHAR pEvent, UCHAR iEventNum)
{
	PXSHORT_D pMap;
	DCHAR i, iRtVal, iLen;

	iRtVal = DIGITMAP_NOTMATCH;
	pMap = (PXSHORT)Sdram_pDataCache;
	for (i = 0; i < Sys_iDigitMapNum; i ++)
	{
		SdramRead(MAP_SDRAM_HI, (UCHAR)(MAP_SDRAM_LO+i), SRAM_DMA_HALF_DWORD);
		iLen = X_VAL(Sdram_pDataCache, SDRAM_DATA_LENGTH);
		iLen >>= 1;
		iLen --;
		if (pMap[iLen])
		{
			//variable length map
			iLen --;
			if (iEventNum > iLen)
			{
				if (_cDigitMapMask[pEvent[iEventNum-1]] & pMap[iLen])
				{
					if (_IsPeriodMatched(pEvent, (UCHAR)(iEventNum - 1), pMap, iLen))
						return DIGITMAP_MATCH;
				}
				else
				{
					if (_IsPeriodMatched(pEvent, iEventNum, pMap, iLen) && iRtVal == DIGITMAP_NOTMATCH)
					{
						iRtVal = DIGITMAP_TOMATCH;
					}
				}
			}
			else if (iEventNum == iLen)
			{
				if (_IsMatched(pEvent, iEventNum) && iRtVal == DIGITMAP_NOTMATCH)
				{
					iRtVal = DIGITMAP_TOMATCH;
				}
			}
			else
			{
				if (_IsMatched(pEvent, iEventNum))
				{
					iRtVal = DIGITMAP_UNDERMATCH;
				}
			}
		}
		else
		{
			if (iEventNum < iLen)
			{
				if (_IsMatched(pEvent, iEventNum))
				{
					iRtVal = DIGITMAP_UNDERMATCH;				
				}
			}
			else if (iEventNum == iLen)
			{
				if (_IsMatched(pEvent, iEventNum))
				{
					return DIGITMAP_MATCH;
				}
			}
		}
	}
	return iRtVal;
}

