#include "StdAfx.h"
#include <GobiAPI.h>
#include "GobiApiOma.h"
#include "FuncList.h"
#include "StatusCtrl.h"
#include "GobiConnectionMgmtApi.h"

#define FUNC_OMADMStartSession				L"OMADMStartSession"
#define FUNC_OMADMCancelSession				L"OMADMCancelSession"
#define FUNC_OMADMGetSessionInfo			L"OMADMGetSessionInfo"
#define FUNC_OMADMGetPendingNIA				L"OMADMGetPendingNIA"
#define FUNC_OMADMSendSelection				L"OMADMSendSelection"
#define FUNC_OMADMGetFeatureSettings		L"OMADMGetFeatureSettings"
#define FUNC_OMADMSetProvisioningFeature	L"OMADMSetProvisioningFeature"
#define FUNC_OMADMSetPRLUpdateFeature		L"OMADMSetPRLUpdateFeature"

#define FUNC_SetOMADMAlertCallback			L"SetOMADMAlertCallback"
#define FUNC_SetOMADMStateCallback			L"SetOMADMStateCallback"

#define PARAM_SessionType					L"SessionType"
#define PARAM_Selection 					L"Selection"
#define PARAM_SessionId						L"SessionId"
#define PARAM_Provisioning					L"Provisioning"
#define PARAM_PrlUpdate						L"PrlUpdate"
#define PARAM_Enable						L"Enable"

CParamList CGobiApiOma::m_sStartSessions;
CParamList CGobiApiOma::m_sSendSelection;
CParamList CGobiApiOma::m_sSetProvisioningFeature;
CParamList CGobiApiOma::m_sSetPrlUpdate;
CParamList CGobiApiOma::m_sSetOMADMStateCallback;
CParamList CGobiApiOma::m_sSetOMADMAlertCallback;

const TableFuncEntry CGobiApiOma::m_TableFunc[] = 
{
	{FUNC_OMADMStartSession, FuncOMADMStartSession, &m_sStartSessions},
	{FUNC_OMADMCancelSession, FuncOMADMCancelSession},
	{FUNC_OMADMGetSessionInfo, FuncOMADMGetSessionInfo},
	{FUNC_OMADMGetPendingNIA, FuncOMADMGetPendingNIA},
	{FUNC_OMADMSendSelection, FuncOMADMSendSelection, &m_sSendSelection},
	{FUNC_OMADMGetFeatureSettings, FuncOMADMGetFeatureSettings},
	{FUNC_OMADMSetProvisioningFeature, FuncOMADMSetProvisioningFeature, &m_sSetProvisioningFeature},
	{FUNC_OMADMSetPRLUpdateFeature, FuncOMADMSetPRLUpdateFeature, &m_sSetPrlUpdate},
	{FUNC_SetOMADMAlertCallback, FuncSetOMADMAlertCallback, &m_sSetOMADMAlertCallback},
	{FUNC_SetOMADMStateCallback, FuncSetOMADMStateCallback, &m_sSetOMADMStateCallback},
	{FUNC_EndOfList}
};

CGobiApiOma::CGobiApiOma(HMODULE hQCDll)
{
	// Initialize the Qualcomm Dll pointer
	m_hQCDll = hQCDll;

	// Define Session Type configurable parameters
	m_sStartSessions.Add(PARAM_SessionType, L"0");

	// Define Send Selection configurable parameters
	m_sSendSelection.Add(PARAM_Selection, L"0");
	m_sSendSelection.Add(PARAM_SessionId, L"0");

	m_sSetProvisioningFeature.Add(PARAM_Provisioning, L"0");
	m_sSetPrlUpdate.Add(PARAM_PrlUpdate, L"0");

	// Define configurable parameters for callback functions
	m_sSetOMADMAlertCallback.Add(PARAM_Enable, L"1");
	m_sSetOMADMStateCallback.Add(PARAM_Enable, L"1");
}

CGobiApiOma::~CGobiApiOma(void)
{
}

BOOL CGobiApiOma::GetAvailFuncList(CFuncList* pFuncList)
{
	TBD_FUNCTION(CGobiApiOma::GetAvailFuncList);

	int iIndex = 0;

	while (m_TableFunc[iIndex].szFuncName.Compare(FUNC_EndOfList))
	{
		pFuncList->Add(L"OMA-DM", m_TableFunc[iIndex].szFuncName, m_TableFunc[iIndex].pParamList);
		TBD_OUTPUT(TBDCT_INFO, TBDOL_INFORMATION, m_TableFunc[iIndex].szFuncName);
		iIndex++;
	}

	return TRUE;
}

UINT CGobiApiOma::ExecuteFunctions(CFuncList* pFuncList, UINT &nTotalExec)
{
	TBD_FUNCTION(CGobiApiOma::Execute);

	int iIndex = 0;
	m_nNumErrors = 0;
	nTotalExec = 0;

	while (m_TableFunc[iIndex].szFuncName.Compare(FUNC_EndOfList))
	{
		if (pFuncList->Find(m_TableFunc[iIndex].szFuncName))
		{
			// Get list of parameters
			CParamList sParams;
			pFuncList->GetFuncParams(m_TableFunc[iIndex].szFuncName, sParams);

			// execute function
			if (!m_TableFunc[iIndex].pFunc(&sParams))
				// increment error counter
				m_nNumErrors++;

			// increment total functions executed
			nTotalExec++;
		}

		iIndex++;
	}

	return m_nNumErrors;
}

BOOL CGobiApiOma::FuncOMADMStartSession(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncOMADMStartSession", STATUSMSG_Send);

	BOOL bRet = FALSE;
    ULONG sessionType;

	// Get user selected parameters
	if (pParams)
	{
		sessionType = _ttoi(pParams->GetValue(PARAM_SessionType));
	}


	ULONG nRet = OMADMStartSession(sessionType);

	CString strTemp;
	strTemp.Format(L"Return: %04d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Compare with QC DLL - can't do start session twice in a row ?
#if 0
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (GOBICMAPI*LPFN_OMADMSTARTSESSION) (ULONG);

		// get pointer to function
		LPFN_OMADMSTARTSESSION pFn = (LPFN_OMADMSTARTSESSION)GetProcAddress_W(m_hQCDll, FUNC_OMADMStartSession);

		// execute function
		if (pFn)
		{
			STRUCT_DeviceCaps sQcDeviceCaps;
			memset(&sQcDeviceCaps, 0, sizeof(STRUCT_DeviceCaps));
			sQcDeviceCaps.nRadioIfacesSize = MAX_RInt;

			LONG nQcRet = pFn(sessionType);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: 0x%04x", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (0 != memcmp(&sQcDeviceCaps, &sDeviceCaps, sizeof(STRUCT_DeviceCaps)))
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}
#endif

	return bRet;
}

BOOL CGobiApiOma::FuncOMADMCancelSession(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncOMADMCancelSession", STATUSMSG_Send);
	UNREFERENCED_PARAMETER(pParams);

	BOOL bRet = FALSE;

	ULONG nRet = OMADMCancelSession();

	CString strTemp;
	strTemp.Format(L"Return: %04d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"OMADM CAncel session successful");
		ADDSTATUS(strTemp, STATUSMSG_Receive);

		bRet = TRUE;
	}

#if 0
	// Compare with QC DLL - can't cancel twice ?

	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (GOBICMAPI*LPFN_GETMODELID) (BYTE, CHAR*);

		// get pointer to function
		LPFN_GETMODELID pFn = (LPFN_GETMODELID)GetProcAddress_W(m_hQCDll, FUNC_GetModelID);

		// execute function
		if (pFn)
		{
			CHAR szQcModelId[MAX_StringLength] = "";

			LONG nQcRet = pFn(MAX_StringLength, szQcModelId);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: 0x%04x", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (0 != strcmp(szQcModelId, szModelId))
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}
#endif

	return bRet;
}

BOOL CGobiApiOma::FuncOMADMGetSessionInfo(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncOMADMGetSessionInfo", STATUSMSG_Send);
	UNREFERENCED_PARAMETER(pParams);

	BOOL bRet = FALSE;

	ULONG SessionState;
	ULONG SessionType;
	ULONG FailureReason;
	BYTE  RetryCount;
	WORD  SessionPause;
	WORD  TimeRemaining;

	ULONG nRet = OMADMGetSessionInfo(&SessionState, &SessionType, &FailureReason, &RetryCount, &SessionPause, &TimeRemaining);

	CString strTemp;
	strTemp.Format(L"Return: %04d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"SessionState: %i", SessionState);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		strTemp.Format(L"SessionType: %i", SessionType);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		strTemp.Format(L"FailureReason: %i", FailureReason);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		strTemp.Format(L"RetryCount: %i", RetryCount);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		strTemp.Format(L"SessionPause: %i", SessionPause);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		strTemp.Format(L"TimeRemaining: %i", TimeRemaining);
		ADDSTATUS(strTemp, STATUSMSG_Receive);

		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (GOBICMAPI*LPFN_OMADMGETSESSIONINFO) (ULONG*, ULONG*, ULONG*, BYTE*, WORD*, WORD*);

		// get pointer to function
		LPFN_OMADMGETSESSIONINFO pFn = (LPFN_OMADMGETSESSIONINFO)GetProcAddress_W(m_hQCDll, FUNC_OMADMGetSessionInfo);

		// execute function
		if (pFn)
		{
			ULONG QcSessionState;
			ULONG QcSessionType;
			ULONG QcFailureReason;
			BYTE  QcRetryCount;
			WORD  QcSessionPause;
			WORD  QcTimeRemaining;

			ULONG nQcRet = pFn(&QcSessionState, &QcSessionType, &QcFailureReason, &QcRetryCount, &QcSessionPause, &QcTimeRemaining);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (QcSessionState != SessionState)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}

	return bRet;
}

BOOL CGobiApiOma::FuncOMADMGetPendingNIA(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncOMADMGetPendingNIA", STATUSMSG_Send);
	UNREFERENCED_PARAMETER(pParams);

	BOOL bRet = FALSE;
	CString strTemp;
	ULONG sessionType = 0xffffffff;  // Initialized to be same as QC dll  
	USHORT sessionId  = 0xffff;      // Initialized to be same as QC dll  

	ULONG nRet = OMADMGetPendingNIA(&sessionType, &sessionId);

	strTemp.Format(L"Return: %04d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"Session Type: %i Session Id: %i", sessionType, sessionId);
		ADDSTATUS(strTemp, STATUSMSG_Receive);
		bRet = (nRet == 0)?TRUE:FALSE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (GOBICMAPI*LPFN_OMADMGETPENDINGNIA) (ULONG*, ULONG*);
		
		// get pointer to function
		LPFN_OMADMGETPENDINGNIA pFn = (LPFN_OMADMGETPENDINGNIA)GetProcAddress_W(m_hQCDll, FUNC_OMADMGetPendingNIA);

		// execute function
		if (pFn)
		{
			ULONG QcsessionType;
			ULONG QcsessionId;

			ULONG nQcRet = pFn(&QcsessionType, &QcsessionId);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else if (QcsessionType != sessionType)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiOma::FuncOMADMSendSelection(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncOMADMSendSelection", STATUSMSG_Send);

	BOOL bRet = FALSE;

	ULONG  selection;
    USHORT sessionId;

	// Get user selected parameters
	if (pParams)
	{
		selection = _ttoi(pParams->GetValue(PARAM_Selection));
		sessionId = (USHORT)_ttoi(pParams->GetValue(PARAM_SessionId));
	}

    ULONG nRet = OMADMSendSelection(selection, sessionId);

	CString strTemp;
	strTemp.Format(L"Return: %04d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (GOBICMAPI*LPFN_OMADMSENDSELECTION) (ULONG, USHORT);

		// get pointer to function
		LPFN_OMADMSENDSELECTION pFn = (LPFN_OMADMSENDSELECTION)GetProcAddress_W(m_hQCDll, FUNC_OMADMSendSelection);

		// execute function
		if (pFn)
		{
			
			ULONG nQcRet = pFn(selection, sessionId);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}

	}

	return bRet;
}

BOOL CGobiApiOma::FuncOMADMGetFeatureSettings(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncOMADMGetFeatureSettings", STATUSMSG_Send);
	UNREFERENCED_PARAMETER(pParams);

	BOOL bRet = FALSE;
	ULONG bProvisioning = 0;
	ULONG bPRLUpdate = 0;

	ULONG nRet = OMADMGetFeatureSettings(&bProvisioning, &bPRLUpdate);

	CString strTemp;
	strTemp.Format(L"Return: %04d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"Provisioning: %i, PRL update: %i", bProvisioning, bPRLUpdate);
		ADDSTATUS(strTemp, STATUSMSG_Receive);

		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (GOBICMAPI*LPFN_OMADMGETFEATURESETTINGS) (ULONG*, ULONG*);

		// get pointer to function
		LPFN_OMADMGETFEATURESETTINGS pFn = (LPFN_OMADMGETFEATURESETTINGS)GetProcAddress_W(m_hQCDll, FUNC_OMADMGetFeatureSettings);

		// execute function
		if (pFn)
		{
			ULONG QcbProvisioning = 0;
			ULONG QcbPRLUpdate = 0;

			ULONG nQcRet = pFn(&QcbProvisioning, &QcbPRLUpdate);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			// QC DLL returns garbage if command fails.  Therefore, only compare return values if nQcRet is SUCCESS.
			else if ((QcbProvisioning != bProvisioning || QcbPRLUpdate != bPRLUpdate) && !nQcRet)
			{
				ADDSTATUS(L"Response differs from Qualcomm DLL", STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiOma::FuncOMADMSetProvisioningFeature(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncOMADMSetProvisioningFeature", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG bProvisioning;

	// Get user selected parameters
	if (pParams)
	{
		bProvisioning = _ttoi(pParams->GetValue(PARAM_Provisioning));
	}
	ULONG nRet = OMADMSetProvisioningFeature(bProvisioning);

	CString strTemp;
	strTemp.Format(L"Return: %04d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"Provisioning set successfully");
		ADDSTATUS(strTemp, STATUSMSG_Receive);

		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (GOBICMAPI*LPFN_OMADMSETPROVISIONINGFEATURE) (ULONG);

		// get pointer to function
		LPFN_OMADMSETPROVISIONINGFEATURE pFn = (LPFN_OMADMSETPROVISIONINGFEATURE)GetProcAddress_W(m_hQCDll, FUNC_OMADMSetProvisioningFeature);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(bProvisioning);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

BOOL CGobiApiOma::FuncOMADMSetPRLUpdateFeature(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncOMADMSetPRLUpdateFeature", STATUSMSG_Send);

	BOOL bRet = FALSE;
	ULONG bPrlUpdate;

	// Get user selected parameters
	if (pParams)
	{
		bPrlUpdate = _ttoi(pParams->GetValue(PARAM_PrlUpdate));
	}
	ULONG nRet = OMADMSetPRLUpdateFeature(bPrlUpdate);

	CString strTemp;
	strTemp.Format(L"Return: %04d", nRet);
	ADDSTATUS(strTemp, STATUSMSG_Receive);

	if (!nRet)
	{
		strTemp.Format(L"PRL Update set successfully");
		ADDSTATUS(strTemp, STATUSMSG_Receive);

		bRet = TRUE;
	}

	// Compare with QC DLL
	if (m_hQCDll)
	{
		// function prototype
		typedef ULONG (GOBICMAPI*LPFN_OMADMSETPRLUPDATEFEATURE) (ULONG);

		// get pointer to function
		LPFN_OMADMSETPRLUPDATEFEATURE pFn = (LPFN_OMADMSETPRLUPDATEFEATURE)GetProcAddress_W(m_hQCDll, FUNC_OMADMSetPRLUpdateFeature);

		// execute function
		if (pFn)
		{
			ULONG nQcRet = pFn(bPrlUpdate);

			if (nQcRet != nRet)
			{
				strTemp.Format(L"QC returned a different status code: %04d", nQcRet);
				ADDSTATUS(strTemp, STATUSMSG_Error);
				bRet = FALSE;
			}
			else
			{
				ADDSTATUS(L"Response matches Qualcomm DLL", STATUSMSG_Status);
				bRet = TRUE;
			}
		}
	}

	return bRet;
}

// OMA-DM Callback tests

static void GOBICALLBACK OMADMAlertCallback(ULONG sessionType, USHORT sessionId)
{
	CString strTemp;
	strTemp.Format(L"Session Type: %d, Session Id: %d", sessionType, sessionId);
	ADDSTATUS(strTemp, STATUSMSG_Notif);  
}

BOOL CGobiApiOma::FuncSetOMADMAlertCallback(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetOMADMAlertCallback", STATUSMSG_Send);

	ULONG ret = 0;

	if (0 != _ttoi(pParams->GetValue(PARAM_Enable)))
	{
		ret = SetOMADMAlertCallback(OMADMAlertCallback);
	}
	else
	{
		ret = SetOMADMAlertCallback(NULL);
	}

	CString strTemp;
	strTemp.Format(L"Result: %04d", ret);
	ADDSTATUS(strTemp, (0==ret)?STATUSMSG_Receive:STATUSMSG_Error);

	return !ret;
}

static void GOBICALLBACK OMADMStateCallback(ULONG sessionState, ULONG failureReason)
{
	CString strTemp;
	strTemp.Format(L"Session State: %d, Failure reason: %d", sessionState, failureReason );
	ADDSTATUS(strTemp, STATUSMSG_Notif);  
}

BOOL CGobiApiOma::FuncSetOMADMStateCallback(CParamList* pParams /*= NULL*/)
{
	ADDSTATUS(L"FuncSetOMADMStateCallback", STATUSMSG_Send);

	ULONG ret = 0;

	if (0 != _ttoi(pParams->GetValue(PARAM_Enable)))
	{
		ret = SetOMADMStateCallback(OMADMStateCallback);
	}
	else
	{
		ret = SetOMADMStateCallback(NULL);
	}

	CString strTemp;
	strTemp.Format(L"Result: %04d", ret);
	ADDSTATUS(strTemp, (0==ret)?STATUSMSG_Receive:STATUSMSG_Error);

	return !ret;
}
