/////////// Structures
struct details
{
	int score;
	int lines;
	int speed;
	int play[100][100];
};

struct Score
{
	int score;
	int lines;
	int speed;
	char name[50];
};

struct HighScore
{
	struct Score info[10];
};

struct font
{
	int matrix[6][8];
};

struct keys
{
	int left;
	int right;
	int drop;
	int rotate;
};

struct config
{
	int players;
	int speed;
	int size;
	int width;
	int height;
	struct keys player1;
	struct keys player2;
};

struct matrix16
{
	int matrix[4][4];
};

struct shape
{
	int rotation[4][4][4];
	int x;
	int y;
	int colour;
	bool active;
};

struct shape2
{
	struct shape matrix[10];
};

struct m
{
	int x;
	int y;
	int b;
};

/////// Structures

//////  Global variables

//Screen info
const int screen_width=80;
const int screen_height=50;
const int pages = 5;
HANDLE	page[pages];
HANDLE console = GetStdHandle(STD_OUTPUT_HANDLE);
HANDLE in = GetStdHandle(STD_INPUT_HANDLE); 
//HANDLE Game1Mutex;
//HANDLE Game2Mutex;
//HANDLE inhand =  GetStdHandle(STD_INPUT_HANDLE); 
int active = 1;
int background_char = ' ';

//Play info
int height = 18;
int width =7;
int playbox_back=0;
int playbox_fore=9;
int play_colour = 0;
int playbox_type = ' ';
int play_char = ' ';

//Blocks info
const int no_blocks=10;
int block_char = 178;

//Colours
int text_colour = 3;
int shadow_col = 1;
int shadow_char = 177;
int background_colour = 0;
int box_border = 6;
int mouse_colour = 9;

//Font info
struct font basic[30];

//Config
struct details player1;
struct details player2;
struct config setup;

//Box info;
int box_shadow=177;

////// Global variables

////// Function prototypes


/////// Draw
void draw(struct shape, int, int, int, int, int);
void draw_play(int);
void draw_screen(int);
void draw_tab(int, int);
/////// Draw

/////// Game
void box(int, int, int, int, int, int, int);
void text_box(char, int, int, int, int, int, int, int, int);
void init_game(void);
void reset_play(void);
void game(int);

int check_line(int);

bool collision(struct shape, int, int, int, struct shape, int, int, int);
bool check(struct shape, int, int, int, int);
bool to_play(struct shape, int, int, int, int, int);

////// Game

////// Menu
void exit_game(void);
void game_type(void);
void keys(void);
void level(void);
void menu(void);
void key_menu(char, int);
void sub_menu(char, char, int);
/////// Menu
int keyb(void);

////// Mouse
struct m mouse(int);
int mouseover(int x1, int y1, int x2, int y2);
bool checkmouse(void);

////// Scores
void highscore(void);
struct HighScore loadscore(char[50]);
void displayscore(struct HighScore, char[50], int, int);

void cls()
{
	COORD topleft = {0, 0};
	DWORD len;
	FillConsoleOutputCharacter(console, background_char, 4000, topleft, & len);
	FillConsoleOutputAttribute(console, background_colour, 4000, topleft, & len);
	return;
}
void locate(int x, int y, int code, int l)
{
	COORD const topleft = {x,y};
	DWORD len;
	SetConsoleCursorPosition(console, topleft);
	FillConsoleOutputAttribute(console, code, l, topleft, & len);
	return;
}
void print(char text[], int x, int y, int c)
{
	COORD point = {x,y};
	int a=point.X;
	DWORD len;
	int length=-1;
	do
	{
		length++;
	}while(text[length]!=char(0));

	for(int i=0;i<length;i++)
	{
		FillConsoleOutputCharacter(console,text[i],1,point, &len); 
		point.X++;
	}
	point.X=a;
	FillConsoleOutputAttribute(console, c, length, point, & len);
}
void put(char text, int x, int y, int c)
{
	COORD point = {x,y};
	DWORD len;
	FillConsoleOutputCharacter(console,text,1,point, &len); 
	FillConsoleOutputAttribute(console, c, 1, point, & len);
}

void fill_area(int x1, int y1, int x2, int y2, char ch, int col)
{
	COORD point = {x1, y1};
	DWORD len;
	
	for(int i=0;i<(y2-y1);i++)
	{
		FillConsoleOutputCharacter(console, ch, x2-x1, point, & len);
		FillConsoleOutputAttribute(console, col, x2-x1, point, & len);
		point.Y++;
	}
}

void screensize()
{
	
	for(int i=0;i<pages;i++)
	{
		page[i] = CreateConsoleScreenBuffer(GENERIC_WRITE,FILE_SHARE_READ,NULL,CONSOLE_TEXTMODE_BUFFER,NULL); 
	}
	COORD const size = {screen_width,screen_height};
	_CONSOLE_CURSOR_INFO ccinfo;
	ccinfo.dwSize = 99;
	ccinfo.bVisible = 0;
	SetConsoleCursorInfo(page[0], &ccinfo);
	SetConsoleScreenBufferSize(page[0], size);
	SetConsoleTitle("Tetris.");
	SetConsoleCursorInfo(page[1], &ccinfo);
	SetConsoleScreenBufferSize(page[1], size);
//	SetConsoleMode(console, ENABLE_MOUSE_INPUT); 
	SetConsoleCursorInfo(console, &ccinfo);
	SetConsoleScreenBufferSize(console, size);
	return;
}

void load_font(char name[])
{
	ifstream fin(name, ios::in|ios::binary);

	for(int i=0;i<57;i++)
	{
		for(int y=0;y<5;y++)
		{
			for(int x=0;x<3;x++)
			{
				fin>>basic[i].matrix[x][y];
			}
			cout<<endl;
		}
		cout<<endl;
	}

	fin.close();
}
void print_font(char text[], int x, int y, int col, int fill)
{
	int length=0;
	int byte=0;
	while(text[length]!=0){length++;}
	for(int i=0;i<length;i++)
	{
		if(text[i]>31&&text[i]<35)
		{
			byte=text[i]-32;
		}
		else
		{
			if(text[i]>38&&text[i]<47)
			{
				byte=text[i]-36;
			}
			else
			{
				if(text[i]>47&&text[i]<60)
				{
					byte=text[i]-37;
				}
				else
				{
					if(text[i]>64&&text[i]<92)
					{
						byte=text[i]-42;
					}
					else
					{
						if(text[i]==93)
						{
							byte=50;
						}
						else
						{
							if(text[i]==63)
							{
								byte=52;
							}
							else
							{
								if(text[i]==124)
								{
									byte=51;
								}
								else
								{
									if(text[i]=='<')
									{
										byte=53;
									}
									else
									{
										if(text[i]=='>')
										{
											byte=54;
										}
										else
										{
											if(text[i]==172)
											{
												byte=55;
											}
											else
											{
												if(text[i]==180)
												{
													byte=56;
												}
											}
										}
									}
								}
							}
						}
					}
				}
			}
		}
		for(int b=0;b<5;b++)
		{
			for(int a=0;a<3;a++)
			{
				if(basic[byte].matrix[a][b]==1)
					put(fill, (x+i*4)+a, y+b, col);
				else
					put(background_char, (x+i*4)+a, y+b, background_colour);
			}
		}
	}
}
void hline(int x, int y, int length, int col)
{
	COORD pos = {x, y};
	DWORD len;
	FillConsoleOutputCharacter(console,char(196),length,pos, &len); 
	FillConsoleOutputAttribute(console,col,length,pos,& len); 
}

void vline(int x, int y, int length, int col)
{
	COORD pos = {x, y};
	DWORD len;
	for(int i=0;i<length;i++)
	{
	FillConsoleOutputCharacter(console,char(179),1,pos, &len); 
	FillConsoleOutputAttribute(console,col,1,pos,& len); 
	pos.Y++;
	}
}

