// common console app definitions
#pragma once
#include "stdafx.h"
#include <Windows.h>
#include <conio.h>
#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <stdlib.h>
#include <cstdio>

using namespace std;
//typedef basic_string<TCHAR> tstring;
#if defined(UNICODE) || defined(_UNICODE)
#define tstring std::wstring
#define tcout std::wcout
#define tcin std::wcin
#define tstringbuf std::wstringbuf
#define tstringstream std::wstringstream
#define tcslen std::wcslen
#else
#define tstring std::string
#define tcout std::cout
#define tcout std::cin
#define tstringbuf std::stringbuf
#define tstringstream std::stringstream
#define tcslen std::strlen
#endif

//
//The following functions execute VPusblib function calls
extern void		DisplaySEUs();
extern void		GetWhoAmI();
extern bool		Connect();
extern bool		ConnectSer();
extern void		Disconnect();
extern void		DevStationMap();
extern void		DevUnits();
extern void		DevFrameRate();
extern void		DevID();
extern void		GetWhoAmISensor(int nsensor);
extern void		SensorFilter(int nsensor);
extern void		SensorFTT(int nsensor); 
extern void		SensorTipOffset(int nsensor);
extern void		SensorIncrement(int nsensor);
extern void		SensorHemisphere(int nsensor);
extern void		SensorBoresight(int nsensor);
extern void		DevConfigPersist();
extern void		ListSerialPorts();
extern void		SourceConfig(int nsource);
extern void		SourceRotation(int nsource);
extern void		DevStylusMode();
extern void		DevInstamapEnable();
extern void		DevInstamapCollect();

//extern void		AsciiMode();
extern void		SetTraceLev(int);
extern bool		FlushPnoBuffer();
extern bool		StartCont();
extern bool		StopCont();
extern bool		GetSingle();
extern bool		ContLoop(int nGet = -1);
extern bool		ContBlockLoop(int nGet = 10);
extern void		DisplayNativeFrame(void*);
extern void		ToggleTraceMode();
extern void		ToggleTimeStamp();

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
typedef enum
{
	CHOICE_CONT
	, CHOICE_SRCSELTEST
	, CHOICE_BLOCK
	, CHOICE_FRAMETEST
	, CHOICE_FRAMETEST_ASYNC_CB
	, CHOICE_TEST_NEWCMD
	, CHOICE_ASYNC_CB_ACCUM
	, CHOICE_DISCONNECT
	, CHOICE_ASCII
	, CHOICE_SINGLE
	, CHOICE_QUIT
	, CHOICE_ENTER
	, CHOICE_RESTART
	, CHOICE_TRACEMODE
	, CHOICE_OPTIONS
	, CHOICE_TRKCMDS
	, CHOICE_SENSCMDS
	, CHOICE_SRCCMDS

	, CMD_CHOICE_DEVSEL
	, CMD_CHOICE_WHOAMI
	, CMD_CHOICE_STAMAP
	, CMD_CHOICE_UNITS
	, CMD_CHOICE_SEUID
	, CMD_CHOICE_FRAMERATE
	, CMD_CHOICE_FILTER
	, CMD_CHOICE_TIPOFF
	, CMD_CHOICE_INCREMENT
	, CMD_CHOICE_HEMISPHERE
	, CMD_CHOICE_FTT
	, CMD_CHOICE_BORESIGHT
	, CMD_CHOICE_PERSIST
	, CMD_CHOICE_SRCCONFIG
	, CMD_CHOICE_SRCROT
	, CMD_CHOICE_STYMODE

	, CHOICE_NONE = -1
} eMenuChoice;

#define ESC	0x1b
#define ENTER 0x0d
#define CTLX 0x18

void		ShowMainMenu();
eMenuChoice MainPrompt();

void		ShowConnectMenu();
eMenuChoice ConnectPrompt();

eMenuChoice TrackerPrompt();


void		ShowSerialMenu();
eMenuChoice	SerialPrompt();

void		DisplayError(int32_t err, const char *szMsg);

void		ShowCommandsMenu();
eMenuChoice CommandsPrompt();

void ShowSensorCommandsMenu();
eMenuChoice SensorCommandsPrompt(int sns);

void ShowSensorSelectMenu(void);
int SensorPrompt(void);

void ShowSourceCommandsMenu();
eMenuChoice SourceCommandsPrompt(int sns);
void ShowSourceSelectMenu(void);
int SourcePrompt(void);

void ShowDevSelectMenu(void);
void DevSelectPrompt(void);

void ShowOptionsMenu();
void OptionsPrompt();

void ShowTraceMenu();
void TracePrompt();

int main_template()
{
	eMenuChoice eChoice = CHOICE_NONE;

	SetConsoleTitle(_T("PolhemusConsole"));

	if (ConnectPrompt() == CHOICE_QUIT)
	{
		eChoice = CHOICE_QUIT;
	}
	else
	{
		ShowMainMenu();
		do
		{
			eChoice = MainPrompt();

			switch (eChoice)
			{
			case CHOICE_BLOCK:
				if (!(StartCont()))
				{
				}
				else
				{
					//Collect/Display Tracker Data until ESC
					ContBlockLoop();
					StopCont();
				}

				break;

			case CHOICE_CONT:
				//Start Cont Mode
				if (!(StartCont()))
				{
				}
				else
				{
					//Collect/Display Tracker Data until ESC
					ContLoop();
					StopCont();
				}

				break;

			case CHOICE_SINGLE:
				//GetSingle();
				break;

			case CHOICE_TRKCMDS:
				//CommandsPrompt();
				break;

			case CHOICE_OPTIONS:
				//OptionsPrompt();
				break;

			case CHOICE_ENTER:
				ShowMainMenu();
				break;

			case CHOICE_RESTART:
				eChoice = ConnectPrompt();
				break;

			case CHOICE_DISCONNECT:
				//Disconnect();
				break;
			case CHOICE_ASCII:
				//AsciiMode();
				break;

			default:
				break;
			}

		} while (eChoice != CHOICE_QUIT);

		Disconnect();

	}

	return 0;
}

/////////////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////////////
const TCHAR * tszMainPrompt = 0;
int nmainmenushow = 0;
void ShowMainMenu()
{
	nmainmenushow++;
	if (tcout.good())
	{ 
		int i = 0;
	}
	else
	{
		uint32_t i = tcout.rdstate();
		//tcout.clear(ios_base::goodbit);
		//tcout.clear();
		std::wcout.clear();
		std::cout.clear();
		tcout.flush();
	}
	/*if (tcin.tie())
	{
		int i = 0;
	}
	else
	{
		int i = 0;
	}*/
	try
	{
		tcout << _T("\n+++Main Menu: \n\n");
		tcout << _T(" C or c:  Continuous Motion Data Display\n");
		tcout << _T(" P or p:  Single Motion Data Frame Display\n");
		tcout << _T(" V or V:  Viper tracker Commands Menu\n");
		tcout << _T(" D or d:  Disconnect\n");
		tcout << _T(" T or t:  Toggle Trace mode \n");
		tcout << _T(" O or o:  Options Menu\n");
		tcout << _T(" G or g:  Test Cal Disable") << endl;
		//tcout << _T(" X or x:  Clear the screen\n");
		//tcout << _T("R or r:  Restart Discovery\n");
		tcout << endl;
		tcout << _T(" ESC:     Quit\n");
		tszMainPrompt = _T("\nCc//Pp//Vv//Dd//Tt//Oo//Gg//ESC>> ");
	}
	catch (exception ex)
	{
		int i = 0;
	}
}

eMenuChoice MainPrompt()
{
	eMenuChoice eRet = CHOICE_NONE;
	INT			ch;

	do
	{
		tcout << tszMainPrompt << flush;
		ch = _gettche();
		ch = toupper(ch);

		switch (ch)
		{
		case 'G':
			eRet = CHOICE_TEST_NEWCMD;
			break;
		case 'X':
			system("cls");
			break;
		case 'A':
			eRet = CHOICE_FRAMETEST_ASYNC_CB;
			break;
		case 'B':
			eRet = CHOICE_BLOCK;
			break;
		case 'C':
			eRet = CHOICE_CONT;
			break;
		case 'D':
			eRet = CHOICE_DISCONNECT;
			break;
		case 'E':
			eRet = CHOICE_ASYNC_CB_ACCUM;
			break;
		case 'F':
			eRet = CHOICE_FRAMETEST;
			break;
		case 'P':
			eRet = CHOICE_SINGLE;
			break;
		case 'O':
			eRet = CHOICE_OPTIONS;
			break;
		case 'R':
			eRet = CHOICE_RESTART;
			break;
		case 'S':
			eRet = CHOICE_SRCSELTEST;
			break;
		case 'T':
			eRet = CHOICE_TRACEMODE;
			break;
		case 'V':
			eRet = CHOICE_TRKCMDS;
			break;
		case ENTER:
			eRet = CHOICE_ENTER;
			break;
		case ESC: // ESC
			eRet = CHOICE_QUIT;
			break;
		default:
			break;
		}
	} while (eRet == CHOICE_NONE);

	return eRet;
}

extern uint32_t g_seuid;
extern int      g_snsid;
extern int		g_srcid;
extern int      g_TraceLevel;
extern bool		g_bFIFO;
extern bool		g_bTimestamp;
const TCHAR *tszCmdPrompt = 0;
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
void ShowCommandsMenu()
{
	tcout << _T("\n+++Commands Menu:  Commands sent to selected device seu ") << g_seuid << endl << endl;
	tcout << _T(" D or d:  Select a different device/seu ") << endl;
	tcout << _T(" I or i:  Get/Set Device ID") << endl;
	tcout << _T(" K or k:  Toggle Self-Cal") << endl;
	tcout << _T(" L or l:  Toggle Self-Cal Collection") << endl;
	tcout << _T(" M or m:  Get Sensor Map\n");
	tcout << _T(" O or o:  Options Menu\n");
	tcout << _T(" P or p:  Persist Current Config\n");
	tcout << _T(" R or r:  Get/Set Frame Rate\n");
	tcout << _T(" S or s:  Sensor Commands\n");
	tcout << _T(" T or t:  Source Commands\n");
	tcout << _T(" U or u:  Set P&O Units\n");
	tcout << _T(" W or w:  Get WhoAmI\n");
	tcout << _T(" Y or y:  Get/Set Stylus Mode\n");
	tcout << _T(" ESC   :  Exit Commands Menu\n");

	tszCmdPrompt = _T("\nDd/Ii/Kk/Ll/Mm/Oo/Pp/Rr/Ss/Uu//Ww//Yy//ESC>> ");
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
eMenuChoice CommandsPrompt()
{
	eMenuChoice eRet = CHOICE_NONE;

	BOOL bContinue = FALSE;
	tcout << endl;
	ShowCommandsMenu();
	do
	{
		bContinue = FALSE;

		INT ch;
		tcout << tszCmdPrompt;
		ch = _getche();
		if (ch == 0)
			ch = _getche();
		ch = toupper(ch);

		switch (ch)
		{
		case ESC:
			eRet = CHOICE_QUIT;
			break;
		case ENTER:
			bContinue = TRUE;
			ShowCommandsMenu();
			break;
		case 'D':
			eRet = CMD_CHOICE_DEVSEL;
			bContinue = TRUE;
			DevSelectPrompt();
			break;
		case 'I':
			eRet = CMD_CHOICE_SEUID;
			bContinue = TRUE;
			DevID();
			break;
		case 'M':
			eRet = CMD_CHOICE_STAMAP;
			DevStationMap();
			break;
		case 'O':
			eRet = CHOICE_OPTIONS;
			OptionsPrompt();
			break;
		case 'P':
			eRet = CMD_CHOICE_PERSIST;
			DevConfigPersist();
			break;
		case 'R':
			eRet = CMD_CHOICE_FRAMERATE;
			DevFrameRate();
			break;
		case 'S':
			eRet = CHOICE_SENSCMDS;
			SensorCommandsPrompt(SensorPrompt());
			break;
		case 'T':
			eRet = CHOICE_SRCCMDS;
			SourceCommandsPrompt(SourcePrompt());
			break;
		case 'U':
			eRet = CMD_CHOICE_UNITS;
			DevUnits();
			break;
		case 'W':
			eRet = CMD_CHOICE_WHOAMI;
			bContinue = TRUE;
			GetWhoAmI();
			break;
		case 'Y':
			eRet = CMD_CHOICE_STYMODE;
			DevStylusMode();
			break;
		default:
			bContinue = TRUE;
			tcout << _T("\nUnsupported Selection 0x") << hex <<  ch << endl;
			break;
		}

	} while (bContinue);

	return eRet;
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
void ShowSensorSelectMenu(void)
{
	tcout << _T("\nCurrently selected Sensor Index is ") << g_snsid;
	if (g_snsid < 0)
		tcout << _T(" (All Sensors)");
	tcout << _T(".\n");
	tcout << _T(" Enter a new numeric Sensor ID. ('*' or -1 Selects all Sensors) \n");
	tcout << _T("\t(Note that wildcard may not be used for Get commands!)\n");
	tcout << _T(" Type ENTER to continue with no change\n");
	tcout << _T("New Sensor Selection (+ENTER)>> ");
}/////////////////////////////////////////////////////////////////////
int SensorPrompt(void)
{
	bool bQuit = false;
	ShowSensorSelectMenu();
	do
	{
		int ch;
		TCHAR input[20];
		memset(input, 0xff, sizeof(input));
		tcin.getline(input, 20, '\n');
		if (tcslen(input) == 0) // just Enter was typed
			ch = ENTER;
		else
			ch = input[0];// _getche();

		switch (ch)
		{
		case ENTER:
			bQuit = true;
			tcout << _T("Selected Sensor Index ") << g_snsid << _T(" unchanged.") << endl;
			break;
		case _T('*'):
			g_snsid = -1;
			tcout << _T("You selected ") << g_snsid << _T(" (All Sensors).") << endl;
			bQuit = true;
			break;
		default:
		{
			int hin;
			tstring strinput(input);
			tstringstream(strinput) >> hin;

			tcout << _T("You selected Sensor Index ") << hin;
			if (hin == -1)
				tcout << _T(" (All Sensors).");

			tcout << endl;
			bQuit = true;

			g_snsid = hin;
		}
		break;
		}

	} while (bQuit == FALSE);

	return g_snsid;
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
void ShowSensorCommandsMenu()
{
	tcout << _T("\n+++Sensor Commands Menu:  ")  << endl << endl;
	tcout << _T(" D or d:  Select a different sensor ") << endl;
	tcout << _T(" B or b:  Get/Set/Reset Boresight") << endl;
	tcout << _T(" F or f:  Get/Set/Reset Filters\n");
	tcout << _T(" H or h:  Get/Set/Reset Hemisphere") << endl;
	tcout << _T(" I or i:  Get/Set/Reset Increment") << endl;
	//tcout << _T(" M or m:  Get Sensor Map\n");
	//tcout << _T("S or s:  Sensor Commands\n");
	tcout << _T(" L or l:  Get/Set/Reset FTT mode\n");
	tcout << _T(" T or t:  Get/Set/Reset Tip Offset\n");
	tcout << _T(" W or w:  Get Sensor WhoAmI\n");
	tcout << _T(" ESC   :  Exit Sensor Commands Menu\n");

	tszCmdPrompt = _T("\nDd//Bb//Ff//Ii//Hh//Ll//Tt//Ww//ESC>> ");
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
eMenuChoice SensorCommandsPrompt(int nsns)
{
	eMenuChoice eRet = CHOICE_NONE;

	BOOL bContinue = FALSE;
	tcout << endl;
	ShowSensorCommandsMenu();
	do
	{
		bContinue = FALSE;

		//TCHAR ch;// INT ch;
		tcout << tszCmdPrompt;
		INT ch = _getche();
		if (ch == 0)
			ch = _getche();
		ch = toupper(ch);

		switch (ch)
		{
		case ESC:
			eRet = CHOICE_QUIT;
			break;
		case ENTER:
			bContinue = TRUE;
			ShowSensorCommandsMenu();
			break;
		case 'B':
			eRet = CMD_CHOICE_BORESIGHT;
			bContinue = TRUE;
			SensorBoresight(g_snsid);
			break;
		case 'D':
			g_snsid = SensorPrompt();
			bContinue = TRUE;
			ShowSensorCommandsMenu();
			break;
		case 'F':
			eRet = CMD_CHOICE_FILTER;
			bContinue = TRUE;
			SensorFilter(g_snsid);
			break;
		case 'I':
			eRet = CMD_CHOICE_INCREMENT;
			bContinue = TRUE;
			SensorIncrement(g_snsid);
			break;
		case 'H':
			eRet = CMD_CHOICE_HEMISPHERE;
			bContinue = TRUE;
			SensorHemisphere(g_snsid);
			break;
			//case 'I':
		//	eRet = CMD_CHOICE_SEUID;
		//	bContinue = TRUE;
		//	DevID();
		//	break;
		case 'L':
			eRet = CMD_CHOICE_FTT;
			bContinue = TRUE;
			SensorFTT(g_snsid);
			break;
		//case 'M':
		//	eRet = CMD_CHOICE_STAMAP;
		//	DevStationMap();
		//	break;
		//case 'S':
		//	eRet = CHOICE_SENSCMDS;
		//	SensorCommandsPrompt();
		//	break;
		//case 'U':
		//	eRet = CMD_CHOICE_UNITS;
		//	DevUnits();
		//	break;
		case 'T':
			eRet = CMD_CHOICE_TIPOFF;
			bContinue = TRUE;
			SensorTipOffset(g_snsid);
			break;
		case 'W':
			eRet = CMD_CHOICE_WHOAMI;
			bContinue = TRUE;
			GetWhoAmISensor(g_snsid);
			break;
		default:
			bContinue = TRUE;
			tcout << _T("\nUnsupported Selection\n");
			break;
		}

	} while (bContinue);

	return eRet;
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
void ShowSourceSelectMenu(void)
{
	tcout << _T("\nCurrently selected Source Index is ") << g_srcid;
	if (g_srcid < 0)
		tcout << _T(" (All Sources)");
	tcout << _T(".\n");
	tcout << _T(" Enter a new numeric Source ID. ('*' or -1 Selects all Sources) \n");
	tcout << _T("\t(Note that wildcard may not be used for Get commands!)\n");
	tcout << _T(" Type ENTER to continue with no change\n");
	tcout << _T("New Source Selection (+ENTER)>> ");
}/////////////////////////////////////////////////////////////////////
int SourcePrompt(void)
{
	bool bQuit = false;
	ShowSourceSelectMenu();
	do
	{
		int ch;
		TCHAR input[20];
		tcin.getline(input, 20);
		if (tcslen(input) == 0) // just Enter was typed
			ch = ENTER;
		else
			ch = input[0];// _getche();

		switch (ch)
		{
		case ENTER:
			bQuit = true;
			tcout << _T("Selected Source Index ") << g_srcid << _T(" unchanged.") << endl;
			break;
		case _T('*'):
			g_srcid = -1;
			tcout << _T("You selected ") << g_srcid << _T(" (All Sources).") << endl;
			bQuit = true;
			break;
		default:
		{
			int hin;
			tstring strinput(input);
			tstringstream(strinput) >> hin;

			tcout << _T("You selected Source Index ") << hin;
			if (hin == -1)
				tcout << _T(" (All Sources).");

			tcout << endl;
			bQuit = true;

			g_srcid = hin;
		}
		break;
		}

	} while (bQuit == FALSE);

	return g_srcid;
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
void ShowSourceCommandsMenu()
{
	tcout << _T("\n+++Source Commands Menu:  ") << endl << endl;
	tcout << _T(" D or d:  Select a different source ") << endl;
	tcout << _T(" C or C:  Get/Set/Reset Source Config") << endl;
	tcout << _T(" R or r:  Get/Set/Reset Source Rotation") << endl;
	tcout << _T(" ESC   :  Exit Source Commands Menu\n");

	tszCmdPrompt = _T("\nTt//Cc//Rr//ESC>> ");
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
eMenuChoice SourceCommandsPrompt(int nsns)
{
	eMenuChoice eRet = CHOICE_NONE;

	BOOL bContinue = FALSE;
	tcout << endl;
	ShowSourceCommandsMenu();
	do
	{
		bContinue = FALSE;

		INT ch;
		tcout << tszCmdPrompt;
		ch = _getche();
		if (ch == 0)
			ch = _getche();
		ch = toupper(ch);

		switch (ch)
		{
		case ESC:
			eRet = CHOICE_QUIT;
			break;
		case ENTER:
			bContinue = TRUE;
			ShowSourceCommandsMenu();
			break;
		case 'C':
			eRet = CMD_CHOICE_SRCCONFIG;
			bContinue = TRUE;
			SourceConfig(g_srcid);
			break;
		case 'D':
			g_srcid = SourcePrompt();
			bContinue = TRUE;
			ShowSourceCommandsMenu();
			break;
		case 'R':
			eRet = CMD_CHOICE_SRCROT;
			bContinue = TRUE;
			SourceRotation(g_srcid);
			break;
		default:
			bContinue = TRUE;
			tcout << _T("\nUnsupported Selection\n");
			break;
		}

	} while (bContinue);

	return eRet;
}

/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////

void ShowDevSelectMenu(void)
{
	DisplaySEUs();
	tcout <<  _T("\nCurrently selected Device/SEU ID is ") << g_seuid;
	if (g_seuid < 0)
		tcout << _T(" (All SEUs)");
	tcout << _T(".\n");
	tcout << _T(" Enter a new numeric SEU ID. ('*' or -1 Selects all SEUs)\n");
	tcout << _T(" Type ENTER to continue with no change\n");
	tcout << _T("New Device/SEU Selection (+ENTER)>> ");
}/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
void DevSelectPrompt(void)
{
	bool bQuit = false;
	ShowDevSelectMenu();
do
{
	int ch;
	TCHAR input[20];
	tcin.getline(input, 20);
	if (tcslen(input) == 0) // just Enter was typed
		ch = ENTER;
	else
		ch = input[0];// _getche();

	switch (ch)
	{
	case ENTER:
		bQuit = true;
		tcout << _T("Selected SEU ID ") << g_seuid << _T(" unchanged.") << endl;
		break;
	case _T('*'):
		g_seuid = -1;
		tcout << _T("You selected ") << g_seuid << _T(" (All SEUs).") << endl;
		bQuit = true;
		break;
	default:
	{
		int hin;
		tstring strinput(input);
		tstringstream(strinput) >> hin;

		tcout << _T("You selected SEU ID ") << hin;
		if (hin == -1)
			tcout << _T(" (All SEUs).");

		tcout << endl;
		bQuit = true;

		g_seuid = hin;
	}
	break;
	}

} while (bQuit == FALSE);
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
enum {
	VIPER_TRACKER
	//, LIBERTY_TRACKER
	//, FASTRAK3_TRACKER

	, TRACKER_MAX

}eTracker;
#define VP_DEVICE_STR  _T("  VIPER")

TCHAR * g_szTrackerType[TRACKER_MAX] =
{
	VP_DEVICE_STR
	//,_T("LIBERTY")
	//,_T("FASTRAK-3")
};
#define VIPER_PID	0xBF01
#define LYHS_PID	0xFF20
#define FT3_PID		0x0003
uint16_t g_trkPID[TRACKER_MAX] =
{
	VIPER_PID			// viper
	//, LYHS_PID		// lib hs runtime
	//, FT3_PID		// ft3
};
int32_t g_TrackerType = VIPER_TRACKER;
uint16_t g_pid = VIPER_PID;
TCHAR * g_pid_name = VP_DEVICE_STR;

extern uint16_t g_vid;// = POLHEMUS_VID;
extern TCHAR * g_vid_name;// = POLHEMUS_MFR_STR;


TCHAR *szConnectPrompt = _T(">> ");
void ShowConnectMenu()
{
	tcout << endl << endl;
	tcout << _T("Commencing Viper dev Discovery when ready.\n") << endl;
	tcout << _T(" V or v:  Change VID parameter. Current: ") << hex << setw(4) << g_vid << g_vid_name << endl;
	tcout << _T(" P or p:  Change PID parameter. Current: ") << hex << g_pid << g_pid_name << endl;
	tcout << _T(" S or s:  Connect via Serial port.") << endl;
	tcout << _T(" ENTER :  Continue with discovery\n");
	tcout << _T(" ESC   :  Abort\n") << endl;
	szConnectPrompt = _T("ENTER//ESC/Vv/Pp//Ss>> ");
	tcout << szConnectPrompt;
}

eMenuChoice ConnectPrompt()
{
	BOOL bQuit = FALSE;
	eMenuChoice eChoice = CHOICE_NONE;
	INT ch;

	ShowConnectMenu();

	uint16_t nVIDin = g_vid;
	uint16_t nPIDin = g_pid;

	do
	{
		ch = _gettche();
		if (ch == ESC)
			return CHOICE_QUIT;

		else if ((ch == 'V') || (ch == 'v'))
		{
			tcout << _T("\n\nEnter new VID >> ");
			TCHAR input[20];
			tcin.getline(input, 20);
			tstring strinput(input);
			tstringstream(strinput) >> nVIDin;
			tcout << _T("You entered ") << hex << nVIDin << endl;
			tcout << _T("Press Enter to continue, ESC to quit>> \n");
			tcout << _T("ENTER//ESC/Vv/Pp>> ");
		}
		else if ((ch == 'P') || (ch == 'p'))
		{
			tcout << _T("\n\nEnter new PID (VIPER=BF01) >> ");
			CHAR input[20];
			cin.getline(input, 20);
			string strinput(input);
			stringstream(strinput) >> hex >> nPIDin;
			tcout << _T("You entered ") << hex << nPIDin << endl;
			tcout << _T("Press Enter to continue, ESC to quit>> \n");
			tcout << _T("ENTER//ESC/Vv/Pp>> ");
			ch = _gettche();
			if (ch == ESC)
				return CHOICE_QUIT;
			g_pid = nPIDin;
			switch (g_pid)
			{
			case VIPER_PID	:
				g_TrackerType = VIPER_TRACKER;
				g_pid_name = VP_DEVICE_STR;
				break;
			default:
				break;
			}
		}
		else if ((ch == 'S') || (ch == 's'))
		{
			eChoice = SerialPrompt();	
		}
		else if (ch == ENTER)
		{
			eChoice = CHOICE_ENTER;
			g_vid = nVIDin;
			g_pid = nPIDin;

			Connect();
			break;
		}
		if (eChoice == CHOICE_NONE)
			ShowConnectMenu();

		else if (eChoice != CHOICE_ENTER)
			tcout << szConnectPrompt;


	} while (eChoice != CHOICE_ENTER);
	//} while (ch != ENTER);


	return eChoice;
}

extern int g_serport; // = 1
TCHAR *szSerPrompt = _T("ENTER//ESC/L/[1-9]>> ");
void ShowSerialMenu()
{
	tcout << endl;
	tcout << _T("Commencing VP serial Discovery when ready.\n") << endl;
	tcout << _T("Serial ports:") << endl;
	ListSerialPorts();
	tcout << _T("Default port selection is ") << g_serport << _T(".") << endl;
	tcout << _T("To select different port, type the port number, or") << endl;
	tcout << _T("L or l:  List Serial Ports available. ") << endl;
	tcout << _T("ENTER :  Continue with connection on port ") << g_serport << _T(".") << endl;
	tcout << _T("ESC   :  Abort\n") << endl;
	tcout << szSerPrompt;
}

eMenuChoice SerialPrompt()
{
	BOOL bQuit = FALSE;
	eMenuChoice eChoice = CHOICE_NONE;
	INT ch;

	ShowSerialMenu();

	int nPortin = g_serport;

	do
	{
		ch = _gettche();
		if (ch == ESC)
			return CHOICE_NONE;

		else if ((ch == 'L') || (ch == 'l'))
		{
			ListSerialPorts();
		}
		else if (isdigit(ch))
		{
			int tmpport = ch - '0';
			tcout << endl << _T("You selected port ") << tmpport << _T(".") << endl;
			g_serport = tmpport;
		}
		else if (ch == ENTER)
		{
			eChoice = CHOICE_ENTER;
			ConnectSer();
			break;
		}

		tcout << szSerPrompt;

	} while (ch != ENTER);


	return eChoice;
}

/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
void ShowOptionsMenu()
{
	tcout << _T("\n+++Options Menu:\n\n");
	tcout << _T(" S or s:  Toggle P&O system timestamp. Current: ") << (g_bTimestamp ? _T("ENABLED") : _T("DISABLED")) << endl;
	tcout << _T(" T or t:  Set VPCmdIF Trace Level. Current: ") << g_TraceLevel << endl;
	tcout << _T(" F or f:  Toggle FIFO P&O collection. Current: FIFO is ") << (g_bFIFO ? _T("ENABLED") : _T("DISABLED")) << endl;
	tcout << _T(" ESC   :  Exit Options Menu\n");
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
void OptionsPrompt()
{
	BOOL bQuit = FALSE;
	tcout << endl;
	ShowOptionsMenu();
	do
	{
		INT ch;

		tcout << _T("\nTt/ESC>> ");
		ch = _getche();
		if (ch == 0)
			ch = _getche();
		ch = toupper(ch);

		switch (ch)
		{
		case 'S':
			ToggleTimeStamp();
			tcout << _T("System timestamp is ") << (g_bTimestamp ? _T("ENABLED") : _T("DISABLED")) << endl;
			break;
		case 'F':
			g_bFIFO = !g_bFIFO;
			tcout << _T("FIFO is ") << (g_bFIFO ? _T("ENABLED") : _T("DISABLED")) << endl;
			break;
		case ESC:
			bQuit = TRUE;
			break;
		case ENTER:
			ShowOptionsMenu();
			break;
		case 'T':
			TracePrompt();
			break;
		default:
			tcout << _T("\nUnsupported Selection\n");
			break;
		}

	} while (bQuit == FALSE);



}

/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
void ShowTraceMenu()
{
	tcout << _T("\n\nCurrent Trace Level is ") << g_TraceLevel << endl;
	tcout << _T("\n\nEnter new Trace Level:\n");
	tcout << _T("0: No Trace\n");
	tcout << _T("1: Minimal Trace + Errors\n");
	tcout << _T("2: Compact I/O Trace + Errors\n");
	tcout << _T("3: Normal I/O Trace + Errors\n");
	tcout << _T("5: Full I/O + Code Trace + Errors\n");
	tcout << _T("7: Verbose\n");
	tcout << _T("Type ENTER to Continue with no selection\n");
	tcout << endl;
	tcout << _T("New Trace Selection>> ");
}
/////////////////////////////////////////////////////////////////////
/////////////////////////////////////////////////////////////////////
void TracePrompt()
{
	bool bQuit = false;
	ShowTraceMenu();
	do
	{
		int ch;
		TCHAR input[20];
		tcin.getline(input, 20);
		if (tcslen(input) == 0) // just Enter was typed
			ch = ENTER;
		else
			ch = input[0];// _getche();

		switch (ch)
		{
		case ENTER:
			bQuit = true;
			tcout << _T("Selected Trace Level ") << g_TraceLevel << _T(" unchanged.") << endl;
			break;
		default:
		{
			int hin;
			tstring strinput(input);
			tstringstream(strinput) >> hin;

			tcout << _T("You selected Trace Level ") << hin;
			if ((hin < 0) || (hin == 4) || (hin == 6) || (hin > 7))
			{
				tcout << _T(" (Invalid!)");

			}
			else
			{
				bQuit = true;
				g_TraceLevel = hin;
				SetTraceLev(hin);
			}
			tcout << endl;
		}
		break;
		}

	} while (bQuit == false);
}

