/*
 * Igra_pari.c
 *
 * Created: 5.6.2017 15:16:14
 * Author : Nejc Gorjup
 */ 

#include <avr/io.h>
#include "LCD_Ili9341.h"
#include "systime.h"
#include "kbd.h"
#include "BackgroundServices.h"
#include <stdlib.h>
#include <stdbool.h> // vkljucitev zaradi true/false nacina, ki ga uporabljam za detekcijo ze odprtih kartic

void Init_IO();
void Game();
int WaitForStart();
int PlayTheGame();
int EndOfGame();
void mix_cards();



int main(void)
{
	Init_IO();
	LCD_Init();
	Systime_Init();
	sei();


	
	while (1)
	{
		if (HasOneMillisecondPassed())
		{
			Game();
		}
		BackgroundServices(); //bere tipke in rise po displayu
	}
}

void Game()
{
	static int state;
	int result;

	switch (state)
	{
		case 1:	//cakanje na zacetek igre
			result = WaitForStart();
			if (result == 1) state++;
		break;
		case 2: //igranje igre
			srand(GetSysTick()); //inicializacija nakljucnega generiranja stevil
			result = PlayTheGame();
			if (result == 1) state++;
		break;
		case 3: //konec igre
			result = EndOfGame();
			if (result == 1) state=1;
		break;
		default: //0 ali neznana vrednost: resetiraj igro
			state = 1;
		break;
	}
}

int WaitForStart()
{
	static int state;
	int result=0;
	char key;
	
	switch(state)
	{
		case 0: //stanje inicializacije
			display_msg = DISP_START_SCREEN;
			KBD_flush(); // pobrise prejsna stanja tipk
			state++;
		break;
		case 1:
			key = KBD_GetKey();
			if(key == BTN_OK)
			{
				state++;
				break;
			}
		break;
		default: //konec-resetiranje avtomata stanj
			result=1;
			state=0;
		break;
	}
	
	return result;
}

int PlayTheGame()
{
	static int state;
	int result=0;
	char key;
//	char txt[50]; // uporabljeno pri debugiranju
	
	static int displayCard[10]={DISP_CARD1,DISP_CARD2,DISP_CARD3,DISP_CARD4,DISP_CARD5,DISP_CARD6,DISP_CARD7,DISP_CARD8,DISP_CARD9,DISP_CARD10};
	static int clearCard[10]={CLEAR_CARD1,CLEAR_CARD2,CLEAR_CARD3,CLEAR_CARD4,CLEAR_CARD5,CLEAR_CARD6,CLEAR_CARD7,CLEAR_CARD8,CLEAR_CARD9,CLEAR_CARD10};
	static int cursor[10]={DISP_CUR1,DISP_CUR2,DISP_CUR3,DISP_CUR4,DISP_CUR5,DISP_CUR6,DISP_CUR7,DISP_CUR8,DISP_CUR9,DISP_CUR10};
	static int clearcursor[10]={CLEAR_CUR1,CLEAR_CUR2,CLEAR_CUR3,CLEAR_CUR4,CLEAR_CUR5,CLEAR_CUR6,CLEAR_CUR7,CLEAR_CUR8,CLEAR_CUR9,CLEAR_CUR10};
	static int i=0;
	display_msg=cursor[i];
	
	static int prejsnjeStanje;
	static int FaceUp;
	
	static int kartica_1;
	static int kartica_2;
	static int prva_odprta_pozicija,pozicija_prej; //pozicija_prej shrani i preden se pomakne
	static int stevec_odprtih;
	static bool ze_odprti[10]={false,false,false,false,false,false,false,false,false,false};
	
	
	int x_index;
	int y_index;
	
	
	switch(state)
	{
		case 0:
			display_msg=DISP_GAME_PLAY_SCREEN;
			state++;
		break;
		case 1:
			display_msg=cursor[i];
			mix_cards();
			stevec_odprtih=0;
			ze_odprti[0]=false;
			ze_odprti[1]=false;
			ze_odprti[2]=false;
			ze_odprti[3]=false;
			ze_odprti[4]=false;
			ze_odprti[5]=false;
			ze_odprti[6]=false;
			ze_odprti[7]=false;
			ze_odprti[8]=false;
			ze_odprti[9]=false;
			state++;
		break;
		case 2: //glej tipke
			key = KBD_GetKey();
			if(key != 0)
			{
				switch (key)
				{
				case BTN_OK:
					if(i>0 && i!=5)
					{
						prejsnjeStanje=clearcursor[i];
						i--;
						display_msg=prejsnjeStanje;
					}
				break;
				
				case BTN_ESC:
					if(i<9 && i!=4)
					{
						prejsnjeStanje=clearcursor[i];
						i++;
						display_msg=prejsnjeStanje;
					}
				break;
				
				case BTN_A:
					if(i<5)
					{
						i=i+5;
						prejsnjeStanje=clearcursor[i-5];
						display_msg=prejsnjeStanje;
					}
					else
					{
						i=i-5;
						prejsnjeStanje=clearcursor[i+5];
						display_msg=prejsnjeStanje;
					}
				break;
				
				case BTN_B:
					if(i<=9)
					{
						if(ze_odprti[i]){ //na novo
						break;
					}
					FaceUp++;
					if(FaceUp==1)
					{
						pozicija_prej=i;
						display_msg=displayCard[i];
						state=3;
						break;
					}
					else if(FaceUp==2)
					{
						display_msg=displayCard[i];
						state=4;
						break;
					}
				}
				break;
			}
			break;
		}
		break;
		
		case 3:
			x_index=i%5;
			y_index=i/5;
			kartica_1=kartice[y_index][x_index]-1; //i ==> vrstica, stolpec
			prva_odprta_pozicija=pozicija_prej;
			state=2;
		break;
		
		case 4:
			x_index=i%5;
			y_index=i/5;
			kartica_2=kartice[y_index][x_index]-1; //i ==> vrstica, stolpec
			state++;
		break;
		
		case 5:
//			sprintf(txt,"k1=%d, k2=%d",kartica_1,kartica_2);  (namenjeno zgolj debugiranju) ali sta kartici isti ali ne.
//			UG_PutString(0,0,txt);

			if(kartica_1!=kartica_2) // ce kartici nista isti
				{
					_delay_ms(500);
					display_msg= clearCard[prva_odprta_pozicija];
					state++;
					break;
				}
			else
			{
			state=7;
			}
		break;
		
		case 6:
			display_msg= clearCard[i];
			FaceUp=0;
			state=2;
		break;
		
		case 7: // ko sta kartici isti
			FaceUp = 0;
			stevec_odprtih++;
			ze_odprti[prva_odprta_pozicija]=true;
			ze_odprti[i]=true;
		
			state=2;
		
			if(stevec_odprtih==5)
			{
				state=11;
			}
		break;
		
		case 11:
			display_msg=DISP_CARD_NONE;
			FaceUp=0;
			i=0;
			state=0;
			result=1;
		break;
		default:
			state = 0;
			result = 1;
		break;
	}

	return result;
}

int EndOfGame()
{
	static int state;
	int result=0;
	static uint32_t zaznamekCasa;
	char key;
	
	switch(state)
	{
		case 0: //stanje inicializacije
			zaznamekCasa=GetSysTick();
			state++;
		break;
		case 1:
			if(Has_X_MillisecondsPassed(1000,&zaznamekCasa))
			{
				display_msg=DISP_END_SCREEN;
				state++;
				break;
			}
		break;
		case 2:
			if(Has_X_MillisecondsPassed(2000,&zaznamekCasa))
			{
				state++;
				KBD_flush();	//pobriši morebitne stare pritiske tipke
			}
		break;
		case 3:
			key = KBD_GetKey();
			if(key == BTN_OK)
			{
				state++;
				break;
			}
			if(Has_X_MillisecondsPassed(10000,&zaznamekCasa))
			{
				state++;
				break;
			}
		break;
		default: //konec-resetiranje avtomata stanj
			result=1;
			state=0;
		break;
	}
	
	return result;
}

void mix_cards()
{
	int i, holder;
	for (i=0; i < 5; i++) //na zacetku se narisejo po vrsti
	{
		kartice [0][i]=i+1;
		kartice [1][i]=i+1;
	}
	for (i=0; i<20; i++) //premesa 20-krat
	{
		
		int x0 = rand()%5;
		int y0 = rand()%2;
		int x1 = rand()%5;
		int y1 = rand()%2;
		
		holder = kartice[y0][x0];
		kartice[y0][x0] = kartice[y1][x1];
		kartice[y1][x1] = holder;
	}
}

void Init_IO()
{
	//DDR: 1-out, 0-in
	PORTB = 0x12;	//0-LCD_DC, 1-buzzer, 2-LCD_CS,
	DDRB = 0x2D;	//3-MOSI, 4-MISO, 5-SCK, 6,7-not implemented
	
	PORTC = 0xF0;	//0..3-analog inputs
	DDRC = 0x00;	//4-SDA(not connected), 5-SCL(not connected), 6,7-not implemented
	
	PORTD = 0xBF;	//0-Rx, 1-Tx, 2..5-buttons
	DDRD = 0xC2;	//6-LCD_BACKLIGHT, 7-LCD_RESET
	
	PORTE = 0x00;	//LEDs
	DDRE = 0xFF;
}
