/*******************************************************************************
 * Copyright (c) 2005 Intel Corporation.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Andy Kaylor, Intel - Initial test implementation
 *
 * $Id: CETester.c,v 1.1 2005/05/27 00:40:00 akaylor Exp $
 *******************************************************************************/ 


#include "TPTPCommon.h"
#include "Extractor.h"
#include <stdio.h>
#include <Windows.h>

// Test data
#define  NUM_MESSAGES          2
#define  NUM_RESULTS_EXPECTED  3

BOOL bUseTPTPUtils = TRUE;

char testMessages[NUM_MESSAGES][1024] = {
                              "<Msg><Cmd src=\"1\" dest=\"2\" ctxt=\"101\"><myCommand1 iid=\"org.eclipse.tptp.platform.cxTester\"></myCommand1></Cmd></Msg>",
                              "<Msg><Cmd src=\"2\" dest=\"3\" ctxt=\"102\"><myCommand1 iid=\"org.eclipse.tptp.platform.cxTester\"></myCommand1></Cmd><Cmd src=\"2\" dest=\"4\" ctxt=\"103\"><myCommand2 iid=\"org.eclipse.tptp.platform.cxTester\"><myParam1>Some Value</myParam1></myCommand2></Cmd></Msg>"
                             };

char expectedCommands[NUM_RESULTS_EXPECTED][1024] = {
                              "<Cmd src=\"1\" dest=\"2\" ctxt=\"101\"><myCommand1 iid=\"org.eclipse.tptp.platform.cxTester\"></myCommand1></Cmd>",
                              "<Cmd src=\"2\" dest=\"3\" ctxt=\"102\"><myCommand1 iid=\"org.eclipse.tptp.platform.cxTester\"></myCommand1></Cmd>",
							  "<Cmd src=\"2\" dest=\"4\" ctxt=\"103\"><myCommand2 iid=\"org.eclipse.tptp.platform.cxTester\"><myParam1>Some Value</myParam1></myCommand2></Cmd>"
                             };
char expectedCommands2[NUM_RESULTS_EXPECTED][1024] = {
                              "<Cmd ctxt=\"101\" dest=\"2\" src=\"1\"><myCommand1 iid=\"org.eclipse.tptp.platform.cxTester\"></myCommand1></Cmd>",
                              "<Cmd ctxt=\"102\" dest=\"3\" src=\"2\"><myCommand1 iid=\"org.eclipse.tptp.platform.cxTester\"></myCommand1></Cmd>",
							  "<Cmd ctxt=\"103\" dest=\"4\" src=\"2\"><myCommand2 iid=\"org.eclipse.tptp.platform.cxTester\"><myParam1>Some Value</myParam1></myCommand2></Cmd>"
                             };
tptp_uint32 expectedDestIDs[NUM_RESULTS_EXPECTED] = { 2, 3, 4 };

int resultsCounter      = 0;
int cmdMismatchesFound  = 0;
int destMismatchesFound = 0;



// Command Extractor DLL name
#ifdef _WIN32
#define CMD_EXTRACTOR_DLL_NAME "../../../bin/tptpCmdExtr.dll"
#else
#define CMD_EXTRACTOR_DLL_NAME "../../../bin/tptpCmdExtr"
#endif

// Local structure to reference command extractor
typedef struct
{
	DLL_REFERENCE                 dllRef;
	createCommandExtractor_ptr_t  createCommandExtractor;
	destroyCommandExtractor_ptr_t destroyCommandExtractor;
	processMessage_ptr_t          processMessage;
} commandExtractor_t;

// Forward declarations
tptp_uint32 processCommand( void *cmh, tptp_uint32 destID, const tptp_string* cmd );
tptp_uint32 logError( void *, tptp_string* err );

// Data for the command extractor
command_extractor_data_t  cxData = { processCommand, logError };

int main(int argc, char* argv[])
{
	commandExtractor_t cx;
	int                errorFound = 0;
	int                ret = 0;
	tptp_object        cxo;
	int                idx;

	// Load the command extractor library
	cx.dllRef = LOAD_LIBRARY( CMD_EXTRACTOR_DLL_NAME );

	if ( cx.dllRef == NULL )
	{
#ifdef _WIN32
		LPVOID lpMsgBuf;
		DWORD  err = GetLastError();

		FormatMessage( 
		    FORMAT_MESSAGE_ALLOCATE_BUFFER | 
		    FORMAT_MESSAGE_FROM_SYSTEM | 
		    FORMAT_MESSAGE_IGNORE_INSERTS,
		    NULL,
		    err,
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
			(LPTSTR) &lpMsgBuf,
			0,
			NULL );

		printf( "Unable to load command extractor library:\n    %s\n", lpMsgBuf );

		// Free the buffer.
		LocalFree( lpMsgBuf );
#else
		printf( "Unable to load command extractor library.\n" );
#endif
		return -1;
	}

	// Get the command extractor entry points
	cx.createCommandExtractor = (createCommandExtractor_ptr_t)RESOLVE_ENTRY_POINT( cx.dllRef, "createCommandExtractor" );
	if ( cx.createCommandExtractor == NULL )
	{
		printf( "Unable to locate entry point: createCommandExtractor\n" );
		errorFound = 1; // continue checking
	}
	cx.destroyCommandExtractor = (destroyCommandExtractor_ptr_t)RESOLVE_ENTRY_POINT( cx.dllRef, "destroyCommandExtractor" );
	if ( cx.destroyCommandExtractor == NULL )
	{
		printf( "Unable to locate entry point: destroyCommandExtractor\n" );
		errorFound = 1; // continue checking
	}
	cx.processMessage = (processMessage_ptr_t)RESOLVE_ENTRY_POINT( cx.dllRef, "processMessage" );
	if ( cx.destroyCommandExtractor == NULL )
	{
		printf( "Unable to locate entry point: processMessage\n" );
		errorFound = 1; // continue checking
	}
	if ( errorFound )
	{
		return -1;
	}

	// Initialize the command extractor
	ret = cx.createCommandExtractor( NULL, &cxData, &cxo );
	if ( ret != 0 )
	{
		printf( "Error returned from createCommandExtractor: %d", ret );
		return -1;
	}
	if ( cxo.data == NULL )
	{
		printf( "Warning: Command extractor did not provide state data.\n" );
	}

	resultsCounter      = 0;
	cmdMismatchesFound  = 0;
	destMismatchesFound = 0;

	// Send some messages
	for ( idx = 0; idx < NUM_MESSAGES; idx++ )
	{
		cx.processMessage( &cxo, strlen(testMessages[idx]), testMessages[idx] );
	}

	// Release the command extractor
	ret = cx.destroyCommandExtractor( &cxo );
	if ( ret != 0 )
	{
		printf( "Error returned from destroyCommandExtractor: %d", ret );
		return -1;
	}

	// Check our results
	if ( resultsCounter != NUM_RESULTS_EXPECTED )
	{
		printf( "Error: %d commands were expected, but %d were processed.\n", NUM_RESULTS_EXPECTED, resultsCounter );
		errorFound = 1;
	}
	if ( cmdMismatchesFound )
	{
		printf( "Error: One or more incoming commands were in an unexpected format.\n" );
		errorFound = 1;
	}
	if ( destMismatchesFound )
	{
		printf( "Error: One or more destinaton IDs were incorrect.\n" );
		errorFound = 1;
	}

	if ( errorFound )
		return -1;

	printf( "Test succeeded.\n" );

	return 0;
}

tptp_uint32 processCommand( void *cmh, tptp_uint32 destID, const tptp_string* cmd )
{
	if ( bUseTPTPUtils )
	{
		if ( strcmp( cmd, expectedCommands2[resultsCounter] ) != 0 )
		{
			printf( "Command %d mismatch:\n   Expected: %s\n   Received: %s\n", resultsCounter, expectedCommands[resultsCounter], cmd );
			cmdMismatchesFound = 1;
		}
	}
	else
	{
		if ( strcmp( cmd, expectedCommands[resultsCounter] ) != 0 )
		{
			printf( "Command %d mismatch:\n   Expected: %s\n   Received: %s\n", resultsCounter, expectedCommands[resultsCounter], cmd );
			cmdMismatchesFound = 1;
		}
	}
	if ( destID != expectedDestIDs[resultsCounter] )
	{
		printf( "Destination %d mismatch: Expected: %d, Received: %d\n", resultsCounter, expectedDestIDs[resultsCounter], destID );
		destMismatchesFound = 1;
	}

	resultsCounter++;

	return 0;
}

tptp_uint32 logError( void *cmh, tptp_string* err )
{
	printf( "Logging error: %s\n", err );
	return 0;
}

