/*
*	Main executable for the SUT server.
*/

#include "stdafx.h"

using namespace TPCE;

#ifndef MAX_PORT
#define MAX_PORT 0xfffe	//for command-line parameter checking
#endif

HANDLE	hListenStopEvent;

//command-line parameters
char*				szDBServer	= "localhost";
char*				szDB		= "tpce";
unsigned short		shPort		= SUTPort;
bool				bVerbose	= false;
eClientDriverType	eClientType = eMDAC;
char*				szMEEToUse	= NULL;

/*
*	Print command-line parameters
*/
void Usage(char *szProgName)
{
	cout<<"Usage: "<<endl;
	cout<<szProgName<<" -s database_server -d database -p port_to_listen_on -c [MDAC/SNAC] -m MEE_Name -v\n";
	cout<<"     -v causes verbose output \n\n";
	cout<<"     MEE_Name (from Benchcraft profile) is required if more than 1 MEE have been launched\n\n";
}

/*
 *       Make sure that the switch value falls between its valid
 *       min and max.  If not print an error message and reset the
 *       the switcth to a valid number.
 */
int CheckSwitch( int value, int min, int max, char *header ) 
{

    if ( value < min  ) {
        fprintf( stderr, "Number of %s must be >= %d - assuming %d\n", header, min, min );
        return( min );
     }
     else if ( value > max ) {
        fprintf( stderr, "Number of %s must be <= %d - assuming %d\n", header, max, max );
        return( max );
     }
     return( value );
}

/*
 *       Parse the command line.
 */
void ParseCommandLine( int argc, char *argv[] )
{
	int   arg;
	char  *sp;
	char  *vp;


	/*
	*  Scan the command line arguments
	*/
	for ( arg = 1; arg < argc; ++arg ) {

		/*
		*  Look for a switch 
		*/
		sp = argv[arg];
		if ( *sp == '-' ) {
			++sp;
		}
		*sp = tolower( *sp );

		/*
		*  Find the switch's argument.  It is either immediately after the
		*  switch or in the next argv
		*/
		vp = sp + 1;
		if ( *vp == 0 ) {
			if ( ++arg > argc && (arg<(argc-1)) && (*argv[arg+1]!='-')) {;
			Usage(argv[0]);
			exit( 1 );
			}
			vp = argv[arg];
		}

		/*
		*  Parse the switch
		*/
		switch ( *sp ) {	  

			case 's':
				szDBServer = vp;
				break;

			case 'd':
				szDB = vp;
				break;			
			
			case 'p':
				shPort = CheckSwitch( atoi( vp ), 1, MAX_PORT, "port to listen on" );
				break;

			case 'c':
				if (_stricmp(vp, "SNAC") == 0)
				{
					eClientType = eSNAC;
				}
				break;

			case 'v':
				bVerbose = true;
				break;

			case 'm':
				szMEEToUse = vp;
				break;

			default:
				Usage(argv[0]);
				exit( 1 );
		}
	}
}

/*
*	Keyboard-reading thread.
*/
void RunKeyboardThread(void *ptr)
{	
	char		c;
	HANDLE		hStdIn;
	DWORD		dwCharsRead;
	int			ret;
	DWORD		Mode = 0;
	CDateTime	TimeNow;

	//cout<<"Keyboard thread started"<<endl;

	hStdIn = GetStdHandle(STD_INPUT_HANDLE);	//get stdin

	Mode = ENABLE_PROCESSED_INPUT;
	SetConsoleMode(hStdIn, Mode);

	while( TRUE )	//get only keyboard events
	{ 
		ret = ReadConsole(hStdIn, &c, 1, &dwCharsRead, NULL);
		if (ret == 0)
			cout<<"Error: "<<GetLastError()<<endl;
		
		if (c=='q')
		{
			TimeNow.SetToCurrent();

			cout<<TimeNow.ToStr(iDateTimeOutputStyle)<<" quitting\n";			
			SetEvent(hListenStopEvent);
			break;
		}
	}

}

//Application start function
int main(int argc, char* argv[])
{
	WSADATA	wsock_data;	

	PrintEGenVersion();

	ParseCommandLine(argc, argv);

	cout<<"Attempting to start server with the following parameters:"<<endl;		
	cout<<"DB Server:         "<<szDBServer<<endl;
	cout<<"DB:                "<<szDB<<endl;
	cout<<"Port to listen on: "<<shPort<<endl;
	cout<<"Client driver:     "<<szClientDriverTypeStr[eClientType]<<endl;
	cout<<"Verbose output:    "<<(bVerbose ? "yes" : "no")<<endl<<endl;
	

	try
	{		
		if ( WSAStartup(2, &wsock_data) != 0 )	//ask for v2 of Windows Sockets
			throw new CSystemErr(CSystemErr::eNone, "SUTServer::main");

		if ( (hListenStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL)) == NULL)
			throw new CSystemErr(CSystemErr::eCreateEvent, "SUTServer::main");

		//Start keyboard thread
		if ( _beginthread(RunKeyboardThread, 0, NULL) == -1L)
			throw new CSystemErr(CSystemErr::ebeginthread, "SUTServer::main");

		CCEServer	serv(	szDBServer, szDB, shPort, bVerbose, 
							hListenStopEvent, eClientType, szMEEToUse);
		cout<<"Server started (press 'q' to shut down)."<<endl;

		serv.ListenAndDispatchThread(NULL);
	}
	catch (CBaseErr *pErr)
	{
		printf("Exception occured on SUT Server: %s error %d in %s\n", 
			pErr->ErrorText(), pErr->ErrorNum(), pErr->ErrorLoc());
	}

	cout<<"Server exited."<<endl;
	return 0;
}
