/*#ifndef UNICODE
#define UNICODE
#endif

#ifndef _UNICODE
#define _UNICODE
#endif
*/

#include <Windows.h>
#include <wininet.h>

#include <stdio.h>
#include <io.h>
#include <conio.h>
#include <fcntl.h>

#include <string>
#include <Shlwapi.h>

#include <signal.h>


//This is a header file taken from cplusplus.com
//http://www.cplusplus.com/articles/Eyhv0pDG/
//concol.h
#ifndef _INC_EKU_IO_CONCOL
#define _INC_EKU_IO_CONCOL
#pragma warning(disable : 4996)
#pragma comment(lib,"Shlwapi.lib")
#pragma comment (lib, "Wininet.lib")
#pragma comment (lib, "User32.lib")

void PrintAPILastError(const char* msg)
{
	if (msg)
		fprintf(stderr, "%s", msg);
	DWORD dwLastError = GetLastError();

	LPVOID lpMsgBuf;

	FormatMessage(
		FORMAT_MESSAGE_ALLOCATE_BUFFER |
		FORMAT_MESSAGE_FROM_SYSTEM |
		FORMAT_MESSAGE_IGNORE_INSERTS |
		FORMAT_MESSAGE_FROM_HMODULE,
		GetModuleHandle(TEXT("wininet.dll")),//NULL
		dwLastError,
		MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
		(LPTSTR)&lpMsgBuf,
		0,
		NULL);

	if (lpMsgBuf) {
		MessageBoxW(NULL, (LPCTSTR)lpMsgBuf, L"Error", MB_OK | MB_ICONERROR);
		LocalFree(lpMsgBuf);
	}

	if (dwLastError == ERROR_INTERNET_EXTENDED_ERROR) {
		DWORD  dwIntError, dwLength = 0;
		TCHAR* szBuffer = NULL;
		InternetGetLastResponseInfo(&dwIntError, NULL, &dwLength);
		if (dwLength) {
			if (!(szBuffer = (TCHAR*)LocalAlloc(LPTR, dwLength))) {
				fprintf(stderr, "Unable to allocate memory to display Internet error code. Error code: %d\n", GetLastError());
				return;
			}
			if (!InternetGetLastResponseInfo(&dwIntError, (LPTSTR)szBuffer, &dwLength)) {
				fprintf(stderr, "Unable to get Intrnet error. Error code: %d\n", GetLastError());
				return;
			}
			MessageBox(NULL, szBuffer, L"Error", MB_OK | MB_ICONERROR);
			LocalFree(szBuffer);
		}
	}
}
bool MoveWin(int x, int y)
{
	HWND hWnd = GetConsoleWindow() ;

	RECT rc;
	GetClientRect(hWnd,&rc);
	return MoveWindow(hWnd, x,y,rc.right-rc.left,rc.bottom-rc.top,true);
}

void pos2Coo(char coo[3],int pos) {
	int p = pos + 1;
	int q = p / 8;
	int r = p % 8;
	coo[0] = char(int('A') + (r - 1));
	itoa(8-q,(coo+1),10);
	coo[2] = 0;
}
int split(char newString[100][100], char* str1, char delim) {
	int i, j, ctr;
	j = 0; ctr = 0;
	for (i = 0; i <= int(strlen(str1)); i++)
	{
		// if space or NULL found, assign NULL into newString[ctr]
		if (str1[i] == delim || str1[i] == '\0')
		{
			newString[ctr][j] = '\0';
			ctr++;  //for next word
			j = 0;    //for next word, init index to 0
		}
		else
		{
			newString[ctr][j] = str1[i];
			j++;
		}
	}
	return ctr;
}
std::string parseNextMove(char* str)
{
	char str1[100] = { 0 };
	char newString[50][100] = { 0 };
	char nv[50][100] = { 0 };
	int i, k, k1;
	char delim = ',';
	char move[100];

	int r = 0;

#define FMT0 "%*1c%[^}][^\n]s"
#define FMT1 "%*[^{]" FMT0

	if (str[0] == '{')
		r = sscanf(str, FMT0, str1);
	else
		r = sscanf(str, FMT1, str1);

#undef FMT1
#undef FMT0

	k = split(newString, str1, delim);


	if (k < 2)
		return std::string();

	int ok = 0;
	for (i = 0; i < k; i++) {
		k1 = split(nv, newString[i], ':');

		if ((2 == k1) && strcmp(nv[0], "\"status\"") == 0) {
			if (stricmp(nv[1], "\"ok\"") == 0) {
				ok = 1;
				continue;
			}
			else {
				ok = 0;
			}
		}
		if ((2 == k1) && ok && stricmp(nv[0], "\"move\"") == 0) {
			sscanf(nv[1], "%*[\"]%[^\"][^\n]", move);
		}
	}
	if (1 == ok) {
		std::string strMove(move);
		return strMove;
	}
	else
		return "";
}
//L"www.chessdb.cn"
//L"/cdb.php?action=querybest&board=rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1&json=1"
char* InetRequest(const wchar_t* URLsrv, const wchar_t* GETRequest) {
	HINTERNET hSession = InternetOpenW(
		L"Mozilla/5.0",
		INTERNET_OPEN_TYPE_PRECONFIG,
		NULL,
		NULL,
		0);
	if (!hSession) {
		PrintAPILastError("InternetOpen()");
	}
	///cdb.php?action=querybest&board=rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR%20w%20KQkq%20-%200%201
	HINTERNET hConnect = 0;
	hConnect = InternetConnectW(
		hSession,
		URLsrv,
		INTERNET_DEFAULT_HTTPS_PORT, // THIS
		L"",
		L"",
		INTERNET_SERVICE_HTTP,
		0,
		0);

	if (NULL == hConnect) {
		PrintAPILastError("InternetConnect()");
	}
	HINTERNET hHttpFile = HttpOpenRequestW(
		hConnect,
		L"GET",
		GETRequest,
		NULL,
		NULL,
		NULL,
		INTERNET_FLAG_SECURE, // THIS
		0);
	if (!hHttpFile) {
		PrintAPILastError("HttpOpenRequest()");
	}
	//while (!HttpSendRequest(hHttpFile, NULL, 0, 0, 0)) {
	if (!HttpSendRequest(hHttpFile, NULL, 0, 0, 0)) {
		//printf("HttpSendRequest error : (%lu)\n");
		PrintAPILastError("HttpSendRequest()");
		/*		InternetErrorDlg(
					GetDesktopWindow(),
					hHttpFile,
					ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED,
					FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
					FLAGS_ERROR_UI_FLAGS_GENERATE_DATA |
					FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS,
					NULL);*/
	}

	DWORD dwFileSize;
	dwFileSize = BUFSIZ;

	char* buffer = 0;
	buffer = new char[dwFileSize + 1];
	while (true) {
		DWORD dwBytesRead;
		BOOL bRead;

		bRead = InternetReadFile(
			hHttpFile,
			buffer,
			dwFileSize + 1,
			&dwBytesRead);

		if (dwBytesRead == 0) break;

		if (!bRead) {
			PrintAPILastError("InternetReadFile error()");
		}
		else {
			buffer[dwBytesRead] = 0;
		}
	}

	InternetCloseHandle(hHttpFile);
	InternetCloseHandle(hConnect);
	InternetCloseHandle(hSession);

	return buffer;
}
namespace eku
{

#ifndef CONCOL
#define CONCOL
	enum concol
	{
		black = 0,
		dark_blue = 1,
		dark_green = 2,
		dark_aqua, dark_cyan = 3,
		dark_red = 4,
		dark_purple = 5, dark_pink = 5, dark_magenta = 5,
		dark_yellow = 6,
		dark_white = 7,
		gray = 8,
		blue = 9,
		green = 10,
		aqua = 11, cyan = 11,
		red = 12,
		purple = 13, pink = 13, magenta = 13,
		yellow = 14,
		white = 15
	};
#endif //CONCOL

	HANDLE std_con_out;
	//Standard Output Handle
	bool colorprotect = false;
	//If colorprotect is true, background and text colors will never be the same
	concol textcol, backcol, deftextcol, defbackcol;

	inline void update_colors()
	{
		CONSOLE_SCREEN_BUFFER_INFO csbi;
		GetConsoleScreenBufferInfo(std_con_out, &csbi);
		textcol = concol(csbi.wAttributes & 15);
		backcol = concol((csbi.wAttributes & 0xf0) >> 4);
	}
	inline void setConsoleWinPos(int left,int top)
	{

	}
	
	inline void setcolor(concol textcolor, concol backcolor)
	{
		if (colorprotect && textcolor == backcolor)return;
		textcol = textcolor; backcol = backcolor;
		unsigned short wAttributes = ((unsigned int)backcol << 4) | (unsigned int)textcol;
		SetConsoleTextAttribute(std_con_out, wAttributes);
	}

	inline void settextcolor(concol textcolor)
	{
		if (colorprotect && textcolor == backcol)return;
		textcol = textcolor;
		unsigned short wAttributes = ((unsigned int)backcol << 4) | (unsigned int)textcol;
		SetConsoleTextAttribute(std_con_out, wAttributes);
	}

	inline void setbackcolor(concol backcolor)
	{
		if (colorprotect && textcol == backcolor)return;
		backcol = backcolor;
		unsigned short wAttributes = ((unsigned int)backcol << 4) | (unsigned int)textcol;
		SetConsoleTextAttribute(std_con_out, wAttributes);
	}

	inline void concolinit()
	{
		std_con_out = GetStdHandle(STD_OUTPUT_HANDLE);
		update_colors();
		deftextcol = textcol; defbackcol = backcol;
	}

	template<class elem, class traits>
	inline std::basic_ostream<elem, traits>& operator<<(std::basic_ostream<elem, traits>& os, concol col)
	{
		os.flush(); settextcolor(col); return os;
	}

	template<class elem, class traits>
	inline std::basic_istream<elem, traits>& operator>>(std::basic_istream<elem, traits>& is, concol col)
	{
		std::basic_ostream<elem, traits>* p = is.tie();
		if (p != NULL)p->flush();
		settextcolor(col);
		return is;
	}


}	//end of namespace eku

#endif	//_INC_EKU_IO_CONCOL
void setFont(int FontSize, const wchar_t* wfontName)
{
	CONSOLE_FONT_INFOEX info = { 0 };
	info.cbSize = sizeof(info);
	info.dwFontSize.X = FontSize; // leave X as zero
	info.dwFontSize.Y = FontSize;
	info.FontWeight = FW_NORMAL;
	wcscpy(info.FaceName, wfontName);
	SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), 0, &info);
}
void restoreFont(CONSOLE_FONT_INFOEX info)
{
	SetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), 0, &info);
}
using namespace std;
using namespace eku;
eku::concol bkgWColor = eku::blue, bkgKColor = eku::dark_blue,
txtColor = eku::black, currCellColor = eku::white, selCellColor = eku::green;
wchar_t* wFontName = (wchar_t*)L"DejaVu Sans Mono";
int fontSize = 72;
CONSOLE_FONT_INFOEX ConsoleFontInfo;
char _ProgName[MAX_PATH] = { 0 };
int board[8][8];
int gamer = 0;
char blacks[16][3] = { 0 };
char whites[16][3] = { 0 };
#define br1 0
#define bn1 1
#define bb1 2
#define bq 3
#define bk 4
#define bb2 5
#define bn2 6
#define br2 7
#define bp1 8
#define bp2 9
#define bp3 10
#define bp4 11
#define bp5 12
#define bp6 13
#define bp7 14
#define bp8 15

#define wr1 0
#define wn1 1
#define wb1 2
#define wq 3
#define wk 4
#define wb2 5
#define wn2 6
#define wr2 7
#define wp1 8
#define wp2 9
#define wp3 10
#define wp4 11
#define wp5 12
#define wp6 13
#define wp7 14
#define wp8 15
void init() {
	strcpy(blacks[br1], "A8");//r=pos
	strcpy(blacks[bn1], "B8");//n=pos
	strcpy(blacks[bb1], "C8");//...
	strcpy(blacks[bq], "D8");
	strcpy(blacks[bk], "E8");
	strcpy(blacks[bb2], "F8");
	strcpy(blacks[bn2], "G8");
	strcpy(blacks[br2], "H8");
	strcpy(blacks[bp1], "A7");
	strcpy(blacks[bp2], "B7");
	strcpy(blacks[bp3], "C7");
	strcpy(blacks[bp4], "D7");
	strcpy(blacks[bp5], "E7");
	strcpy(blacks[bp6], "F7");
	strcpy(blacks[bp7], "G7");
	strcpy(blacks[bp8], "H7");

	strcpy(whites[wr1], "A1");
	strcpy(whites[wn1], "B1");
	strcpy(whites[wb1], "C1");
	strcpy(whites[wq], "D1");
	strcpy(whites[wk], "E1");
	strcpy(whites[wb2], "F1");
	strcpy(whites[wn2], "G1");
	strcpy(whites[wr2], "H1");
	strcpy(whites[wp1], "A2");
	strcpy(whites[wp2], "B2");
	strcpy(whites[wp3], "C2");
	strcpy(whites[wp4], "D2");
	strcpy(whites[wp5], "E2");
	strcpy(whites[wp6], "F2");
	strcpy(whites[wp7], "G2");
	strcpy(whites[wp8], "H2");


}

void toUp(char* arr) {
	for (char* c = arr; *c = toupper(*c); ++c);
}
void splitMove(char sFrom[3], char sTo[3], const char* resp) {
	//char sFrom[3],sTo[3];
	if (resp && strlen(resp) == 4) {
		strncpy(sFrom, resp, 2);
		sFrom[2] = 0;
		strncpy(sTo, resp + 2, 2);
		sTo[2] = 0;
	}
	return;
}
int getItem(char* coo) {
	for (int i = 0; i < 16; i++) {
		if ((blacks[i][0] == coo[0]) && (blacks[i][1] == coo[1]))
			return i;
	}
	for (int i = 0; i < 16; i++) {
		if ((whites[i][0] == coo[0]) && (whites[i][1] == coo[1]))
			return 20 + i; //Se il pezzo e' bianco aggiungo 20 all'indice per semplificare
	}
	return -1;
}
char mapPiece(int i) {
	switch (i) {
	case 0:
	case 7:
		return 'r';
	case 1:
	case 6:
		return 'n';
	case 2:
	case 5:
		return 'b';
	case 3:
		return 'q';
	case 4:
		return 'k';

	case 8:
	case 9:
	case 10:
	case 11:
	case 12:
	case 13:
	case 14:
	case 15:
		return 'p';
	}
	switch (i) {
	case 20:
	case 27:
		return 'R';
	case 21:
	case 26:
		return 'N';
	case 22:
	case 25:
		return 'B';
	case 23:
		return 'Q';
	case 24:
		return 'K';

	case 28:
	case 29:
	case 30:
	case 31:
	case 32:
	case 33:
	case 34:
	case 35:
		return 'P';
	}
	return 0;
}
int getPiece(int i) {
	switch (i) {
	case 0:
	case 7:
		return 0x265C;//r
	case 1:
	case 6:
		return 0x265E;//n
	case 2:
	case 5:
		return 0x265D;//b
	case 3:
		return 0x265B;//q
	case 4:
		return 0x265A;//k	

	case 8:
	case 9:
	case 10:
	case 11:
	case 12:
	case 13:
	case 14:
	case 15:
		return 0x265F;//p
	}
	switch (i) {
	case 20:
	case 27:
		return 0x2656;//R
	case 21:
	case 26:
		return 0x2658;//N
	case 22:
	case 25:
		return 0x2657;//B
	case 23:
		return 0x2655;//Q
	case 24:
		return 0x2654;//K	

	case 28:
	case 29:
	case 30:
	case 31:
	case 32:
	case 33:
	case 34:
	case 35:
		return 0x2659;//P
	}
	return -1;
}
int iCurr = 48;
int iSelFrom = -1;
int iSelTo = -1;
void drawPiece(int index, int pos, eku::concol b) {
	eku::setbackcolor(b);
	eku::settextcolor(txtColor);
	if (pos == iCurr)
		eku::setbackcolor(currCellColor);
	if (pos == iSelFrom)
		eku::setbackcolor(selCellColor);
	int p = getPiece(index);
	if (p >= 0)
		wprintf(L"%c", p);
}

eku::concol getBkgCell(int i, int j) {
	eku::concol c;
	if ((i + j) % 2 == 0)
		c = bkgKColor;
	else
		c = bkgWColor;
	return c;
}
void drawCell(int index, eku::concol b) {
	if (index == iCurr)
		eku::setbackcolor(currCellColor);
	else
		eku::setbackcolor(b);
	if (index == iSelFrom)
		eku::setbackcolor(selCellColor);
	wprintf(L" ");
}

void drawGame() {
	char coo[3];
	int index=0;
	eku::concol b;
	//system("cls");

	//Draw coo
	wprintf(L" ");
	for (int i = 0; i < 8; i++) {
		eku::setbackcolor(eku::black);
		eku::settextcolor(eku::white);
		wprintf(L"%c", 'a' + i);
	}
	wprintf(L"\n");
	for (int i = 7; i > -1; i--) {
		eku::setbackcolor(eku::black); eku::settextcolor(eku::white);
		wprintf(L"%d", i + 1);
		for (int j = 0; j < 8; j++) {
			coo[0] = 'A' + j;
			coo[1] = '0' + i + 1;
			coo[2] = '\0';
			index = getItem(coo);
			b = getBkgCell(i, j);
			if (index >= 0) {
				drawPiece(index, (7 - i) * 8 + j, b);
			}
			else {
				drawCell((7 - i) * 8 + j, b);
			}
		}
		//Draw Coo 
		eku::setbackcolor(eku::black); eku::settextcolor(eku::white);
		wprintf(L"%d\n", i + 1);
	}

	wprintf(L" ");
	for (int i = 0; i < 8; i++) {
		eku::setbackcolor(eku::black); eku::settextcolor(eku::white);
		wprintf(L"%c", 'a' + i);
	}
}
void showCursor(int visible)
{
	HANDLE consoleHandle = GetStdHandle(STD_OUTPUT_HANDLE);
	CONSOLE_CURSOR_INFO info;
	GetConsoleCursorInfo(consoleHandle, &info);
	info.bVisible = visible;
	SetConsoleCursorInfo(consoleHandle, &info);
}
void drawBoard() {

	int N = 8;
	int i, j;
	eku::concol c;

	for (i = 0; i < N; i++) {
		for (j = 0; j < N; j++) {
			if (i % 2 == 0)
				if (j % 2 == 0)
					c = bkgWColor;
				else
					c = bkgKColor;
			else
				if (j % 2 == 0)
					c = bkgKColor;
				else
					c = bkgWColor;
			eku::setbackcolor(c);
			wprintf(L" ");
		}
		wprintf(L"\n");

	}
}
#include <sstream>
string BuildFEN() {
	std::stringstream ss;
	int kb = 0;
	char coo[3];
	int index;
	for (int i = 7; i > -1; i--) {
		for (int j = 0; j < 8; j++) {
			coo[0] = 'A' + j;
			coo[1] = '0' + i + 1;
			coo[2] = '\0';
			index = getItem(coo);
			//b = getBkgCell(i, j);
			if (index >= 0) {
				if (kb > 0) {
					ss << kb;
					kb = 0;
				}
				ss << mapPiece(index);
			}
			else {
				kb++;
			}

		}
		if (kb > 0) {
			ss << kb;
			kb = 0;
		}
		if (i > 0)
			ss << "/";

	}

	ss << " " << (gamer == 0 ? 'w' : 'b');
	ss << " KQkq - 0 1";
	ss << "&json=1";

	return ss.str();
}
void FENSave(const char* fileName) {

	FILE* fp = NULL;
	fp = fopen(fileName, "w");
	if (!fp)
		return;

	fprintf(fp, "https://www.chessdb.cn/cdb.php?action=querybest&board=");
	fprintf(fp, "%s", BuildFEN().c_str());

	fclose(fp);

}
TCHAR* getProgName() {
	TCHAR* out;
	//GetModuleFileNameA(GetModuleHandle(NULL), szPath, MAX_PATH);
	
	TCHAR  buffer[MAX_PATH] = { 0 };
	
	DWORD bufSize = sizeof(buffer) / sizeof(*buffer);
	// Get the fully-qualified path of the executable
	if (GetModuleFileName(NULL, buffer, bufSize) == bufSize)
	{
		// the buffer is too small, handle the error somehow
	}
	// now buffer = "c:\whatever\yourexecutable.exe"

	// Go to the beginning of the file name
	out = PathFindFileName(buffer);
	// now out = "yourexecutable.exe"

	// Set the dot before the extension to 0 (terminate the string there)
	*(PathFindExtension(out)) = 0;
	return out;
}
char* FromWide(char* out,wchar_t* wide)
{
	size_t len = WideCharToMultiByte(CP_UTF8, 0, wide, -1, NULL, 0, NULL, NULL);
	if (len == 0)
		return NULL;

	if (out)
		WideCharToMultiByte(CP_UTF8, 0, wide, -1, out, len, NULL, NULL);
	return out;
}

void help()
{
	stringstream ss;
	ss << "Chess program in shell CUI for Windows\n\t(By Fischetti P.)\n\n? Suggeest move\nh this help\nR Redraw\n\n" << "USAGE:" << _ProgName << " -fFontName[" << wFontName << "] -zFontSize[72]\n" << " -wc(white cell color) -kc(black cell color) -tc(piece color) -sc(curr cell color) " <<
		"\n	 black = 0,\n\
	 dark_blue = 1,\n\
	 dark_green = 2,\n\
	 dark_aqua, dark_cyan = 3,\n\
	 dark_red = 4,\n\
	 dark_purple = 5, dark_pink = 5, dark_magenta = 5,\n\
	 dark_yellow = 6,\n\
	 dark_white = 7,\n\
	 gray = 8,\n\
	 blue = 9,\n\
	 green = 10,\n\
	 aqua = 11, cyan = 11,\n\
	 red = 12,\n\
	 purple = 13, pink = 13, magenta = 13,\n\
	 yellow = 14,\n\
	 white = 15\n";
	//"chess progroam in shell GUI for Windows\n/? Suggeest move\nhH this help\n r R Redraw"
	MessageBoxA(NULL, ss.str().c_str(), _ProgName, MB_OK | MB_ICONINFORMATION);
}

void redrawGame() {
	settextcolor(deftextcol);
	setbackcolor(defbackcol);
	system("cls");
	drawGame();
}

void doArrowKeys(char input) {
	switch (input)
	{

	case 72: {//up
		if (iCurr - 8 >= 0) {
			iCurr -= 8;
			redrawGame();
		}
	}
		   break;
	case 75: {//left
		if (iCurr > 0) {
			iCurr--;
			redrawGame();
		}
	}
		   break;
	case 77: {//right
		if (iCurr < 63) {
			iCurr++;
			redrawGame();
		}
	}
		   break;
	case 80: {//down
		if ((iCurr + 8) < 64) {
			iCurr += 8;
			redrawGame();
		}
	}
		   break;
	}
}
void quitPrg() {
	//FENSave("fen.txt");
	restoreFont(ConsoleFontInfo);
	settextcolor(deftextcol);
	setbackcolor(defbackcol);
	showCursor(1);

	system("pause");

	showCursor(1);
	exit(0);
}
int IsTurn(int indexPiece, int gamer) {
	
	if (indexPiece < 20 && gamer == 1) {
		OutputDebugString(L"OKB");
		return 1;
    }
	if (indexPiece >= 20 && gamer == 0) {
		OutputDebugString(L"OKW");
		return 1;
	}
	OutputDebugString(L"N");
	return 0;
}
void move(char* sFrom, char* sTo) {
	toUp(sFrom);
	toUp(sTo);
	int k = getItem(sFrom);

	if (k >= 20) {
		whites[k - 20][0] = sTo[0];
		whites[k - 20][1] = sTo[1];
	}
	else {
		blacks[k][0] = sTo[0];
		blacks[k][1] = sTo[1];
	}
	gamer = !gamer;
	redrawGame();
}
void doKeys(char input) {
	switch (input) {
	case 13: {//return

		if (iSelFrom == -1) {
			char coo[3] = { 0 };
			pos2Coo(coo, iCurr);
			int index = -1;
			if ((index = getItem(coo)) != -1) {
				if (IsTurn(index, gamer)) {
					iSelFrom = iCurr;
					redrawGame();/*
					char *sFrom = &coo[0];
					char *sTo = &coo[1];
					move(sFrom, sTo);*/
				}
			}
		}
		else {
			char coo[3] = { 0 };
			pos2Coo(coo, iCurr);
			if (iSelFrom == iCurr) {
				iSelFrom = -1;
				iSelTo = -1;
				redrawGame();
			}
			else {
				int index = -1;
				if ((index = getItem(coo)) == -1) {
					//if(IsTurn(index, gamer)){
					char cooFrom[3] = { 0 };
					pos2Coo(cooFrom, iSelFrom);
					iSelTo = iCurr;
					//redrawGame();
					char* sFrom = cooFrom;
					char* sTo = coo;
					iSelFrom = iSelTo = -1;
					move(sFrom, sTo);
				}

			}
		}
	}
	
		   break;
	case 63://? http req move
	{

		std::string req = "/cdb.php?action=querybest&board=" + BuildFEN();
		std::wstring wstr = std::wstring(req.begin(), req.end());
		const wchar_t* GETRequest = wstr.c_str();

		char* pBuff = InetRequest(L"www.chessdb.cn", GETRequest);
		//const char* resp = strResp.c_str();
		if (pBuff && strlen(pBuff) > 0) {
			std::string strResp = parseNextMove(pBuff);//"{\"status\":\"ok\",\"move\":\"c2c3\"}");
			if (strResp.length() == 0)
				MessageBoxA(NULL, pBuff, "Error", MB_OK | MB_ICONERROR);
			else {
				const char* pResp = strResp.c_str();
				if (MessageBoxA(NULL, pResp, "Move?", MB_OKCANCEL | MB_ICONINFORMATION) == IDOK) {
					char sFrom[3] = { 0 }, sTo[3] = { 0 };
					splitMove(sFrom, sTo, pResp);
					move(sFrom, sTo);
				}
			}
			free(pBuff);
			pBuff = 0;
		}
		//L"/cdb.php?action=querybest&board=rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1&json=1");
	}
	break;
	case 82://R
	case 114://r
		redrawGame();
		break;
	case 85://S
	case 115://s
		FENSave("fen.txt");
		break;
	case 72:
	case 104:
		help();
		break;
	case 27://ESC	 
	//default:
		quitPrg();
		break;
	}

}
void handler_quit(int signal) {
	quitPrg();
	exit(0);
}
int main(int argc, char* argv[])
{
	signal(SIGINT, handler_quit);
	signal(SIGABRT, handler_quit);
	TCHAR *prgName = getProgName();
	FromWide(_ProgName, prgName);
	//_ProgName = argv[0];
	for (int i = 1; i < argc; i++)
	{
		if (('-' == argv[i][0]) || ('/' == argv[i][0]))
		{
			char cp;
			cp = argv[i][1];
			switch (cp)
			{
			case 'w':
			case 'W':
				bkgWColor = (eku::concol)atoi(&argv[i][2]);
				break;
			case 'k':
			case 'K':
				bkgKColor = (eku::concol)atoi(&argv[i][2]);
				break;
			case 't':
			case 'T':
				txtColor = (eku::concol)atoi(&argv[i][2]);
				break;
			case 's':
			case 'S':
				currCellColor = (eku::concol)atoi(&argv[i][2]);
				break;
			case 'f':
			case 'F': {
				MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, &argv[i][2], -1, wFontName, MAX_PATH);
			}
					break;
			case 'z':
			case 'Z': {
				fontSize = atoi(&argv[i][2]);
			}
					break;
			case '?':
			case 'h':
			{help(); return 1; }
			default:
			{help(); return -1; }
			}
		}
		else
		{
			help(); return -1;
		}
	}
	system("cls");
	showCursor(0);

	_setmode(_fileno(stdout), _O_U16TEXT);
	//SetConsoleMaxSize();
	MoveWin(0,0);

	ConsoleFontInfo.cbSize = sizeof(ConsoleFontInfo);
	if (!GetCurrentConsoleFontEx(GetStdHandle(STD_OUTPUT_HANDLE), 0, &ConsoleFontInfo)) {
		PrintAPILastError("GetCurrentConsoleFontEx");
		return -1;
	}
	setFont(fontSize, wFontName);
	concolinit();
	wchar_t wBuff[MAX_PATH];
	MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, "CUI CHESS", -1, wBuff, MAX_PATH);
	SetConsoleTitleW(wBuff);
	settextcolor(red);
	init();

	drawGame();
	int IsArrowKey = 0;
	char input;

	while (true)
	{
		showCursor(0);
		input = getch();
		if (0 == input || -32 == input) {
			IsArrowKey = 1;
			continue;
		}
		else {
			if (1 == IsArrowKey)
				doArrowKeys(input);
			else
				doKeys(input);
			IsArrowKey = 0;
		}



	}

	quitPrg();
	return 0;
}