/**@@@+++@@@@******************************************************************
**
** Microsoft Windows Media
** Copyright (C) Microsoft Corporation. All rights reserved.
**
***@@@---@@@@******************************************************************
*/

// #include <stdio.h>
// #include <string.h>
//#include <stdlib.h>
#include "DX_VOS_String.h"
#include "DX_VOS_Mem.h"
#include "drmcommon.h"
#include "apiParams.h"
#include "tOEMIMP.h"

char* TrimSpaceLeft(char *s)
{
	if (s) {
		while (*s && OEM_isspace((unsigned char)*s))
			s++;
	}
	return s;
}

char* TrimSpace(char *s)
{
	char *pEnd;
	s = TrimSpaceLeft(s);
	if (s) {
		pEnd = s + DX_VOS_StrLen(s);
		while (pEnd > s && OEM_isspace((unsigned char)*(pEnd - 1)))
			pEnd--;
		*pEnd = '\0';
	}
	return s;
}

int ParseTCID(char* szLine, long *pTCID, char **ppTCTitle)
{
	char *pTitle;

	if (!OEM_isdigit((unsigned char)*szLine))
		return 0;

	if (pTCID)
		*pTCID = atol(szLine);

	if (ppTCTitle) {
		pTitle = DX_VOS_StrChr(szLine, ':');
		*ppTCTitle = pTitle? TrimSpace(pTitle + 1) : NULL;
	}
	return 1;
}

char* StringDup(char *pStr)
{
	char *pOut = NULL;
	DxSize_t len;
	len = DX_VOS_StrLen(pStr) + 1;
	if (pOut = (char*)DX_VOS_MemMalloc(len))
		DX_VOS_StrNCopy(pOut,len, pStr);
	return pOut;
}

void FreeAPIParams(TAPIParams *pParams)
{
	int i;
	for (i = 0; i < pParams->m_lParamCount; i++)
		DX_VOS_MemFree(pParams->m_szParams[i]);
	
	DX_VOS_MemFree(pParams->m_szParams);
	DX_VOS_MemFree(pParams->m_szAPIName);
	DX_VOS_MemSet(pParams, 0, sizeof(TAPIParams));
}

DRM_RESULT TranslateHr(char* s)
{
	/* use a symbolic lookup map later */
	return (DRM_RESULT)atol(s); 
}

typedef enum {T_FUNCTION_NAME, T_PARAMETER, T_EXP_VALUE} EToken;

static char* GetToken(char *pLine, EToken *pToken)
{
	static EToken tokenNext = T_FUNCTION_NAME;
	static char *pNext = NULL;
	char *pOut, *p, *q;
	if (pLine) {
		pNext = pLine;
		tokenNext = T_FUNCTION_NAME;
	}

	if (!(pNext && *pNext))
		return NULL;

	pOut = pNext = TrimSpaceLeft(pNext);
	*pToken = tokenNext;

	switch (tokenNext) {
	case T_FUNCTION_NAME:
		p = DX_VOS_StrChr(pOut, '(');
		q = DX_VOS_StrChr(pOut, '=');
		if (p && (!q || q > p)) {
			*p = 0;
			pNext = p + 1;
			tokenNext = T_PARAMETER;
		} else if (q && (!p || p > q)) {
			*q = 0;
			pNext = q + 1;
			tokenNext = T_EXP_VALUE;
		} else
			pNext = NULL;
		break;
	case T_PARAMETER:
		if (*pOut == '"') { /* Search the ending quote for the literal string */
			pOut++;
			p = pOut; q = pOut;
			while (*q && *q != '"') {
				if (*q == '\\') /* '\' is the escape char */
					q++;
				if (!(*q))
					break;
				*p++ = *q++;
			}
			pNext = (*q)? q + 1: NULL;
			*p = 0;
		}
		if (pNext) {
			p = DX_VOS_StrChr(pNext, ',');
			q = DX_VOS_StrChr(pNext, ')');
			if (p && (!q || q > p)) {
				*p = 0;
				pNext = p + 1;
			} else if (q && (!p || p > q)) {
				*q = 0;
				q = DX_VOS_StrChr(q + 1, '=');
				pNext = q? q + 1: NULL;
				tokenNext = T_EXP_VALUE;
			}
		}
		break;
	case T_EXP_VALUE:
		pNext = NULL;
		break;
	}
	return TrimSpace(pOut);
}

static long GetParamCount(char *pLine)
{
	long count = 0;
	EToken token;
	char *s = StringDup(pLine);
	
	if (GetToken(s, &token)) {
		do {
			if (token == T_PARAMETER)
				count++;
		} while (GetToken(NULL, &token));
	}

	DX_VOS_MemFree(s);
	return count;
}

/* 
	Parse an API line in the text file to the TAPIParams struct.
	All these are valid api lines:
	API_Name
	API_Name = ExpValue
	API_Name(param)
	API_Name(param)=ExpValue
	API_Name(param1, param2, param3)=ExpValue
	API_Name("Param(v1, v2)", param2)
	API_Name(param1, "Param(\"string\")", param2)
	API_Name(param1, "param is backslash\\")
*/
int ParseAPI(char *pLine, TAPIParams *pParams)
{
	EToken token;
	long lParamCount;
	char *pCurToken;

	FreeAPIParams(pParams);

	lParamCount = GetParamCount(pLine);
	pParams->m_drExpected = DRM_SUCCESS;
	pParams->m_fExcept = FALSE;
	if (lParamCount) {
		pParams->m_szParams = (char**)DX_VOS_MemMalloc(sizeof(char*) * lParamCount);
		DX_VOS_MemSet(pParams->m_szParams, 0, sizeof(char*) * lParamCount);
	}

	pCurToken = GetToken(pLine, &token);
	if (pCurToken) {
		do {
			switch (token) {
				case T_FUNCTION_NAME:
					pParams->m_szAPIName = StringDup(pCurToken);
					break;
				case T_EXP_VALUE:
					if (*pCurToken == '!') {
						pParams->m_fExcept = TRUE;
						pCurToken++;
					}
					pParams->m_drExpected = TranslateHr(pCurToken);
					break;
				case T_PARAMETER:
					if (pParams->m_lParamCount < lParamCount) {
						if (!DX_VOS_StrCmp(pCurToken, "NULL")) /* if the parameter is "NULL", then set the value to NULL */
							pParams->m_szParams[pParams->m_lParamCount] = NULL;

						else if (!DX_VOS_StrCmp(pCurToken, "EMPTY")) /* if the parameter is "EMPTY", then set the value to an empty string */
							pParams->m_szParams[pParams->m_lParamCount] = StringDup("");
						
						else
							pParams->m_szParams[pParams->m_lParamCount] = StringDup(pCurToken);
						
						pParams->m_lParamCount++;
					}
					break;
			}
		} while (pCurToken = GetToken(NULL, &token));
	}

	return (pParams->m_szAPIName != NULL);
}

