#include "Header.h"

/* Genes decoder: genotype -> phenotype */
std::tuple<int, double, bool> decode(std::string& dna, int& it)
{
	int i;
	std::string genes;

	// Finger
	for (i = it * 12; i < (it * 12) + 4; ++i)
		genes += dna[i];

	int first = std::stoi(genes, nullptr, 2);

	// Condition of the finger (folded or not)
	genes = "";

	for (; i < (it * 12) + 11; ++i)
		genes += dna[i];

	double second = (double)std::stoi(genes, nullptr, 2)/100;

	// Lowercase or uppercase
	bool third = dna[(it * 12) + 11] != '0';

	return std::make_tuple(first, second, third);
}


/* What key is pressed according to the condition
    of the finger */
bool pos(int& first, double& second, int index)
{
	switch (first)
	{
		// 4 positions
	case Primate::lRing:
	case Primate::lMiddle:
	case Primate::rMiddle:
	case Primate::rRing:
		if (second >= .25 * index && second < .25 * (index + 1))
			return true;
		else
			return false;
		break;

		// 6 positions
	case Primate::lPinky:
		if (second >= .167 * index && second < .167 * (index + 1))
			return true;
		else
			return false;
		break;

		// 8 positions
	case Primate::lIndex:
	case Primate::rIndex:
		if (second >= .125 * index && second < .125 * (index + 1))
			return true;
		else
			return false;
		break;

		// 10 positions
	case Primate::rPinky:
		if (second >= .1 * index && second < .1 * (index + 1))
			return true;
		else
			return false;
		break;
	}
}


/* Keyboard ANSI-INCITS 154-1988 (US standard) 'emulator' */
char keyboard(int& first, double& second, bool& third)
{
	// Default: null
	char key = char(0); 

	if (!third)
	{
		switch (first)
		{
		case Primate::lPinky:
			if	(pos(first, second, 5))	key = '`';
			else if (pos(first, second, 4)) key = '1';
			else if (pos(first, second, 3)) key = '\t';
			else if (pos(first, second, 2)) key = 'q';
			else if (pos(first, second, 1)) key = 'a';
			else if (pos(first, second, 0)) key = 'z';
			break;

		case Primate::lRing:
			if	(pos(first, second, 3))	key = '2';
			else if (pos(first, second, 2)) key = 'w';
			else if (pos(first, second, 1)) key = 's';
			else if (pos(first, second, 0)) key = 'x';
			break;

		case Primate::lMiddle:
			if	(pos(first, second, 3))	key = '3';
			else if (pos(first, second, 2)) key = 'e';
			else if (pos(first, second, 1)) key = 'd';
			else if (pos(first, second, 0)) key = 'c';
			break;

		case Primate::lIndex:
			if	(pos(first, second, 7))	key = '4';
			else if (pos(first, second, 6)) key = '5';
			else if (pos(first, second, 5)) key = 'r';
			else if (pos(first, second, 4)) key = 't';
			else if (pos(first, second, 3)) key = 'f';
			else if (pos(first, second, 2)) key = 'g';
			else if (pos(first, second, 1)) key = 'v';
			else if (pos(first, second, 0))	key = 'b';
			break;

		case Primate::lThumb:
		case Primate::rThumb:
			key = ' ';
			break;

		case Primate::rIndex:
			if	(pos(first, second, 7))	key = '6';
			else if (pos(first, second, 6)) key = '7';
			else if (pos(first, second, 5)) key = 'y';
			else if (pos(first, second, 4)) key = 'u';
			else if (pos(first, second, 3)) key = 'h';
			else if (pos(first, second, 2)) key = 'j';
			else if (pos(first, second, 1)) key = 'n';
			else if (pos(first, second, 0)) key = 'm';
			break;

		case Primate::rMiddle:
			if	(pos(first, second, 3))	key = '8';
			else if (pos(first, second, 2)) key = 'i';
			else if (pos(first, second, 1)) key = 'k';
			else if (pos(first, second, 0)) key = ',';
			break;

		case Primate::rRing:
			if	(pos(first, second, 3))	key = '9';
			else if (pos(first, second, 2)) key = 'o';
			else if (pos(first, second, 1)) key = 'l';
			else if (pos(first, second, 0)) key = '.';
			break;

		case Primate::rPinky:
			if	(pos(first, second, 9))	key = '0';
			else if (pos(first, second, 8)) key = '-';
			else if (pos(first, second, 7)) key = '=';
			else if (pos(first, second, 6)) key = 'p';
			else if (pos(first, second, 5)) key = '[';
			else if (pos(first, second, 4)) key = ']';
			else if (pos(first, second, 3)) key = '\\';
			else if (pos(first, second, 2)) key = ';';
			else if (pos(first, second, 1)) key = '\'';
			else if (pos(first, second, 0)) key = '/';
			break;

		default:
			// If the gene is repressed: null
			key = char(0); 
			break;
		}
	}
	else
	{
		switch (first)
		{
		case Primate::lPinky:
			if	(pos(first, second, 5))	key = '~';
			else if (pos(first, second, 4)) key = '!';
			else if (pos(first, second, 3)) key = '\t';
			else if (pos(first, second, 2)) key = 'Q';
			else if (pos(first, second, 1)) key = 'A';
			else if (pos(first, second, 0)) key = 'Z';
			break;

		case Primate::lRing:
			if	(pos(first, second, 3))	key = '@';
			else if (pos(first, second, 2)) key = 'W';
			else if (pos(first, second, 1)) key = 'S';
			else if (pos(first, second, 0)) key = 'X';
			break;

		case Primate::lMiddle:
			if	(pos(first, second, 3))	key = '#';
			else if (pos(first, second, 2)) key = 'E';
			else if (pos(first, second, 1)) key = 'D';
			else if (pos(first, second, 0)) key = 'C';
			break;

		case Primate::lIndex:
			if	(pos(first, second, 7))	key = '$';
			else if (pos(first, second, 6)) key = '%';
			else if (pos(first, second, 5)) key = 'R';
			else if (pos(first, second, 4)) key = 'T';
			else if (pos(first, second, 3)) key = 'F';
			else if (pos(first, second, 2)) key = 'G';
			else if (pos(first, second, 1)) key = 'V';
			else if (pos(first, second, 0)) key = 'B';
			break;

		case Primate::lThumb:
		case Primate::rThumb:
			key = ' ';
			break;

		case Primate::rIndex:
			if	(pos(first, second, 7))	key = '^';
			else if (pos(first, second, 6)) key = '&';
			else if (pos(first, second, 5)) key = 'Y';
			else if (pos(first, second, 4)) key = 'U';
			else if (pos(first, second, 3)) key = 'H';
			else if (pos(first, second, 2)) key = 'J';
			else if (pos(first, second, 1)) key = 'N';
			else if (pos(first, second, 0)) key = 'M';
			break;

		case Primate::rMiddle:
			if	(pos(first, second, 3))	key = '*';
			else if (pos(first, second, 2)) key = 'I';
			else if (pos(first, second, 1)) key = 'K';
			else if (pos(first, second, 0)) key = '<';
			break;

		case Primate::rRing:
			if	(pos(first, second, 3))	key = '(';
			else if (pos(first, second, 2)) key = 'O';
			else if (pos(first, second, 1)) key = 'L';
			else if (pos(first, second, 0)) key = '>';
			break;

		case Primate::rPinky:
			if	(pos(first, second, 9))	key = ')';
			else if (pos(first, second, 8)) key = '_';
			else if (pos(first, second, 7)) key = '+';
			else if (pos(first, second, 6)) key = 'P';
			else if (pos(first, second, 5)) key = '{';
			else if (pos(first, second, 4)) key = '}';
			else if (pos(first, second, 3)) key = '|';
			else if (pos(first, second, 2)) key = ':';
			else if (pos(first, second, 1)) key = '\"';
			else if (pos(first, second, 0)) key = '?';
			break;

		default:
			// If the gene is repressed: null
			key = char(0); 
			break;
		}
	}

	return key;
}