// replay.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include "LogParser.h"
#include "SAXContentHandlerImpl.h"
#include <iostream>

#include "options.h"

const char * optv[] = {
	"r:resultfile <string>",
	"d:msgdelay <number>",
	"w:wait <number>",
	"s:startdelay <number>",
	"p:path <string>"
};

void convertTCharToChar(const TCHAR * source, char ** dest) {
#ifdef UNICODE
	std::wstring wstr(source);
    int size_needed = WideCharToMultiByte(CP_UTF8, 0, &wstr[0], (int)wstr.size(), NULL, 0, NULL, NULL);
    std::string strTo( size_needed, 0 );
    WideCharToMultiByte                  (CP_UTF8, 0, &wstr[0], (int)wstr.size(), &strTo[0], size_needed, NULL, NULL);
	*dest = new char[strTo.size()+1];
	memcpy((void*)*dest, strTo.c_str(), strTo.size()+1);
#else
	std::string str(source);
	*dest = new char[strTo.size()+1];
	memcpy(*dest, strTo.c_str(), strTo.size()+1);
#endif
}

void convertCharToTChar(const char * source, TCHAR ** dest) {
#ifdef UNICODE
	std::string str(source);
	int size_needed = MultiByteToWideChar(CP_UTF8, 0, &str[0], (int)str.size(), NULL, 0);
	std::wstring wstrTo( size_needed, 0 );
	MultiByteToWideChar                  (CP_UTF8, 0, &str[0], (int)str.size(), &wstrTo[0], size_needed);
	*dest = new TCHAR[wstrTo.size()+1];
	memcpy((void*)*dest, wstrTo.c_str(), (wstrTo.size()+1)*sizeof(TCHAR));
#else
	std::string str(source);
	*dest = new char[strTo.size()+1];
	memcpy(*dest, strTo.c_str(), strTo.size()+1);
#endif
}

int _tmain(int argc, _TCHAR* argv[])
{
	if( argc < 3 ) {
		std::wcout << L"Usage: " << argv[0] << L"<replayfile> <applicationundertest> [-r <resultfile>] [-d <useDefaultDelay>] [-w <waitAfterFinish>] [-p <workingPath>] [-s <startupDelay>]" << std::endl;
		return 1;
	}

	int optchar = 0;
	const char * optarg;
	// set default values
	TCHAR * resultfile = NULL;
	int msgdelay = 0;
	int startdelay = 5000;
	int wait = 1;
	TCHAR * workingPath = NULL;

	int argc_char = argc-2;
	char ** argv_char = new char*[argc_char];

	// convert argv to char*[]
	convertTCharToChar(argv[0], &argv_char[0]);
	for( int i=3; i<argc; i++ ) {
		convertTCharToChar(argv[i], &argv_char[i-2]);
	}

	// parse options
	Options opts(*argv_char, optv);
	OptArgvIter iter(--argc_char, ++argv_char);
	while( optchar = opts(iter, optarg) ) {
		switch(optchar) {
			case 'r':
				convertCharToTChar(optarg, &resultfile);
				break;
			case 'd':
				msgdelay = atoi(optarg);
				break;
			case 'w':
				wait = atoi(optarg);
				break;
			case 'p':
				convertCharToTChar(optarg, &workingPath);
				break;
			case 's':
				startdelay = atoi(optarg);
				break;
			default:
				break;
		}
	}
	for( int i=0; i<argc_char; i++ ) {
		delete[] argv_char[i];
	}
	//delete[] argv_char; //TODO does not work?!

	TCHAR * replayfile = argv[1];
	TCHAR * appUnderTest = argv[2];

	// initialize COM library for the current thread
	CoInitialize(NULL); 
	MSXML2::ISAXXMLReader* pXMLReader = NULL;

	// create an instance of the XML reader
	HRESULT hr = CoCreateInstance(
		__uuidof(MSXML2::SAXXMLReader), 
		NULL, 
		CLSCTX_ALL, 
		__uuidof(MSXML2::ISAXXMLReader), 
		(void **)&pXMLReader);

	if( !FAILED(hr) ) {
		TestResults results(replayfile);
		std::wcout << L"replaying sessions in " << argv[1] << std::endl;
		LogParser * parser = new LogParser(appUnderTest, startdelay, &results, (bool) msgdelay);
		parser->setWorkingPath(workingPath);
		pXMLReader->putContentHandler(parser);
		hr = pXMLReader->parseURL(replayfile);
		if( hr!=S_OK ) {
			std::wcout << L"failure parsing XML file" << std::endl;
			return 1;
		}
		pXMLReader->Release();
		std::wcout << L"================================================" << std::endl;
		std::wcout << L"replay completed" << std::endl;
		if( resultfile!=NULL ) {
			results.write(resultfile);
			std::wcout << L"results written to " << resultfile << std::endl;
		}
	}

	CoUninitialize();
	
	if( wait!=0 ) {
		std::wcout << L"press enter to exit ...";
		getchar();
	}

	delete resultfile;

	return 0;
}

