package 
{
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.display.SimpleButton;
	import flash.events.MouseEvent;
	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;
	import flash.utils.Timer;
	import flash.events.TimerEvent;
	import flash.geom.Point; 
    import flash.geom.Rectangle; 
	import flash.display.BitmapData;
	import flash.text.TextField;
	import flash.text.TextFormat;
	import flash.text.TextFieldAutoSize;
	import Field;
	import Figures;
	import Texts;
	
	[SWF(width='470', height='520', backgroundColor='#151515', frameRate='30')]

	public class Main extends Sprite 
	{
		// прикрепляем ресурсы
		[Embed(source = 'graphics/button1.png')] private var button_n: Class;
		[Embed(source = 'graphics/button2.png')] private var button_o: Class;
		[Embed(source = 'graphics/button3.png')] private var button_d: Class;
		[Embed(source = 'graphics/logo.png')] private var logo_c: Class;
		private var startButton: SimpleButton;
		private var button_on: Bitmap;					 // три
		private var button_no: Bitmap;					 // стадии
		private var button_do: Bitmap;					 // кнопки
		private var logo: Bitmap;
		private var field: Field;						 // игровое поле
		private var isup: int = 3;
		private var isleft: int = 3;
		private var isright: int = 3;
		private var isdown: int = 3;
		private var isgame: int = 0;
		private var TimerTick: Timer;
		private var fig: Figures = new Figures();		 // описание фигур 
		private var tex: Texts = new Texts();			 // тексты
		private var rotat: int;							 // поворот фигуры
		private var speed: int;							 // скорость падения фигур
		private var delay: int;							 // задержка при вращении фигуры(зажатая кнопка)
		private var nowfig: int;						 // текущая фигура
		private var nextfig: int;						 // следующая фигура
		private var levelCount: int;					 // счётчик уровня
		private var scoreCount: int;					 // счётчик очков
		private var linesCount: int;					 // счётчик линий
		private var BestScore: int;						 // лучший результат
		
		public function Main():void 
		{
			if (stage) init();
			else addEventListener(Event.ADDED_TO_STAGE, init);
		}
		
		// инит
		private function init(e:Event = null):void 
		{
			removeEventListener(Event.ADDED_TO_STAGE, init);
			// кнопка
			button_on = new button_o();
			button_no = new button_n();
			button_do = new button_d();
			startButton = new SimpleButton();
			startButton.upState = button_no;
			startButton.downState = button_do;
			startButton.overState = button_on;
			startButton.hitTestState = button_no;
			startButton.x = 75;
			startButton.y = 300;
			startButton.addEventListener(MouseEvent.CLICK, clickStart);
			addChild(startButton);
			// поле
			field = new Field();
			// логотипчик
			logo = new logo_c;
			logo.x = 145;
			logo.y = 80;
			addChild(logo);
			// слушатели нажатия клавиш
			stage.addEventListener(KeyboardEvent.KEY_DOWN, myKeyDown);
			stage.addEventListener(KeyboardEvent.KEY_UP, myKeyUp);
			// таймер
			TimerTick = new Timer(32);
			TimerTick.addEventListener(TimerEvent.TIMER, MainLoop);
			TimerTick.start();
			// добавляем блоки по краю поля
			for (var j: int = 0; j < field.MAP_SIZE_Y; j++)
			{
				field.Grid[0][j].z = 3; 
				field.Grid[field.MAP_SIZE_X - 1][j].z = 3; 
				if (j < field.MAP_SIZE_X)
				{
					field.Grid[j][0].z = 3; 
					field.Grid[j][field.MAP_SIZE_Y-1].z = 3; 
				}
			}
			// рандомим фиугры
			nowfig = Math.round(Math.random() * 6);
			nextfig = Math.round(Math.random() * 6);
			// выводим лучший результат
			addChild(tex.BestScoreText);
			tex.BestScoreText.text = 'BEST SCORE: ' + BestScore;
			centerTexts();
			// рисуем панельки на игровом экране
			field.View.graphics.beginFill(0x272727);
			field.View.graphics.drawRoundRect(330, 20, 120, 480, 15, 15);
			field.View.graphics.beginFill(0x484848);
			field.View.graphics.drawRoundRect(330, 20, 120, 30, 15, 15);
			field.View.graphics.beginFill(0x484848);
			field.View.graphics.drawRoundRect(330, 194, 120, 30, 15, 15);
			field.View.graphics.beginFill(0x484848);
			field.View.graphics.drawRoundRect(330, 295, 120, 30, 15, 15);
			field.View.graphics.beginFill(0x484848);
			field.View.graphics.drawRoundRect(330, 396, 120, 30, 15, 15);
			field.View.graphics.beginFill(0x272727);
			field.View.graphics.drawRoundRect(20, 20, 290, 480, 15, 15);
		}
		
		// чистим поле
		private function clear(): void
		{
			for (var i: int = 0; i < 5; i++)
			{
				for (var j: int = 0; j < 5; j++)
				{
					if (fig.figures[nowfig][rotat][j][i] > 0)
					{
						field.Grid[field.PlayX + i][field.PlayY + j].z = 0; 
					}
				}
			}	
		}
		
		// записываем текущую фигуру в поле
		private function push(): void
		{
			for (var i: int = 0; i < 5; i++)
			{
				for (var j: int = 0; j < 5; j++)
				{
					if (fig.figures[nowfig][rotat][j][i] > 0)
					{
						field.Grid[field.PlayX + i][field.PlayY + j].z = fig.figures[nowfig][rotat][j][i]; 
					}
				}
			}	
		}
		
		// удаляем собранные линии
		private function del(y: int): void
		{
			for (var i: int = 1; i < 11; i++)
			{
				field.Grid[i][y].z = 0; 
			}	
						
			for (var j: int = y; j > 2; j--)
			{
				for (var l: int = 1; l < 11; l++)
				{
					field.Grid[l][j].z = field.Grid[l][j-1].z; 
				}	
			}
			linesCount += 1;
			tex.LinesValueText.text = String(linesCount);
			levelCount = linesCount / 10 + 1;
			if (levelCount > 10) levelCount = 10;
			tex.LevelValueText.text = String(levelCount);
			centerTexts();
		}
		
		// проверяем на наличие собранных линий
		private function lines(): void
		{
			var points: int;
			var count: int;
			points = 0;
			for (var i: int = 1; i < 21; i++)
			{
				count = 0;
				for (var j: int = 1; j < 11; j++)
				{
					if (field.Grid[j][i].z > 0) count += 1; 
				}
				if (count == 10)
				{
					del(i);
					points += 1;
				}
			}
			if (points > 0)
			// начисляем по 100, 300, 500, 700 за 1, 2, 3, 4 собранные линии соответсвенно
			scoreCount += points * 200 - 100;
			tex.ScoreValueText.text = String(scoreCount);
			centerTexts();
		}
		
		// обновляем показатель следующей фигуры
		private function updateShowNext(): void
		{
			field.ShowNext.bitmapData = new BitmapData(100, 152, true, 0x00000000);
			for (var i: int = 4; i > 0; i--)
			{
				for (var j: int = 0; j < 5; j++)
				{
					if (fig.figures[nextfig][0][i][j] > 0)
					field.ShowNext.bitmapData.copyPixels(field.blocks.bitmapData, new Rectangle ( (fig.figures[nextfig][0][i][j]-1)*20, 0 , 20, 32 ), new Point ( fig.showstp[nextfig].x+j*20 , fig.showstp[nextfig].y+i*20));
				}
			}	
		}
		
		// заканчиваем ход
		private function endmove(): void
		{
			if ((canmove(field.PlayX, field.PlayY + 1)) == false)
			{
				// если не можем больше двигаться вниз
				push();
				field.PlayY = 0;
				field.PlayX = 3;
				nowfig = nextfig;
				nextfig = Math.round(Math.random() * 6);
				rotat = 0;
				lines();
				
				updateShowNext();
				// проверяем на конец игры, если да то выходим в меню и обновляем лучший результат
				if (isend() == true)
				{
					if (scoreCount > BestScore) BestScore = scoreCount;
					startButton.visible = true;
					field.View.visible = false;
					field.Img.visible = false;
					field.ShowNext.visible = false;
					isgame = 0;
					tex.NextText.visible = false;
					tex.LevelText.visible = false;
					tex.LinesText.visible = false;
					tex.ScoreText.visible = false;
					tex.LevelValueText.visible = false;
					tex.LinesValueText.visible = false;
					tex.ScoreValueText.visible = false;
					tex.BestScoreText.text = 'BEST SCORE: ' + BestScore;
					tex.BestScoreText.visible = true;
					logo.visible = true;
					centerTexts();
				}
			}
		}
		
		// проверяем на возможность добавить новую фигуру
		private function isend(): Boolean
		{
			var isendgame: Boolean = false;
			for (var i: int = 0; i < 5; i++)
			{
				for (var j: int = 0; j < 5; j++)
				{
					if ((fig.figures[nowfig][rotat][j][i] > 0) && (field.Grid[3+i][j].z > 0))
					{
						isendgame = true;
					}
				}
			}
			return isendgame;
		}
		
		// проверяем на возможность двинуть фигуру
		private function canmove(x:int,y: int): Boolean
		{
			clear();
			var iscan: Boolean = true;
			for (var i: int = 0; i < 5; i++)
			{
				for (var j: int = 0; j < 5; j++)
				{
					if ((fig.figures[nowfig][rotat][j][i] > 0 && field.Grid[x + i][y + j].z > 0)
					|| (fig.figures[nowfig][rotat][j][i] > 0 && field.PlayX+i < 0)
					|| (fig.figures[nowfig][rotat][j][i] > 0 && field.PlayX+i > field.MAP_SIZE_X-1)
					|| (fig.figures[nowfig][rotat][j][i] > 0 && field.PlayY+j < 0)
					|| (fig.figures[nowfig][rotat][j][i] > 0 && field.PlayY+j > field.MAP_SIZE_Y-1))
					{
						iscan = false;
					}
				}
			}
			return iscan;
		}
		
		// проверяем на возможность повернуть фигуру
		private function canrotate(rot: int): Boolean
		{
			var iscan: Boolean = true;
			rot += 1;
			if (rot == 4) rot = 0;
			for (var i: int = 0; i < 5; i++)
			{
				for (var j: int = 0; j < 5; j++)
				{
					if ((fig.figures[nowfig][rot][j][i] > 0 && field.PlayX+i > field.MAP_SIZE_X ) 
					|| (fig.figures[nowfig][rot][j][i] > 0 && field.PlayY+j > field.MAP_SIZE_Y )) iscan = false;;
					
					if ((fig.figures[nowfig][rot][j][i] > 0 && field.PlayY+j < field.MAP_SIZE_Y ) 
					&& (fig.figures[nowfig][rot][j][i] > 0 &&  field.PlayX+i < field.MAP_SIZE_X )) 
					{
						if ((field.Grid[field.PlayX + i][field.PlayY + j].z > 0)
						|| (field.PlayY+j<0) || (field.PlayX+i<0)) iscan = false;
					}
				}
			}
			return iscan;
		}
		
		// основной цикл
		private function MainLoop(event:TimerEvent):void
		{
			if (isgame == 1) 
			{
				
				if (isdown > 1)
				{
					speed += 1;
					if (speed >= 34-levelCount*3)
					{
						endmove();
						clear();
						if (canmove(field.PlayX,field.PlayY+1))
						field.PlayY += 1;
						speed = 0;
					}
				}
				
				// чистим битма игрового поля перед наполнением
				field.Img.bitmapData = new BitmapData(240, 480, true, 0x00000000);
				
				// добавляем текущую фигуру в поле
				push();

				// заполняем битмап
				for (var i: int = 0; i < field.MAP_SIZE_X; i++)
				{
					for (var j: int = 0; j < field.MAP_SIZE_Y; j++)
					{
						if (field.Grid[i][field.MAP_SIZE_Y-1-j].z > 0)
						field.Img.bitmapData.copyPixels(field.blocks.bitmapData, new Rectangle ( (field.Grid[i][field.MAP_SIZE_Y-1-j].z-1)*20, 0 , 20, 32 ), new Point ( field.Grid[i][field.MAP_SIZE_Y-1-j].x - field.CENTER_X + 100 , field.Grid[i][field.MAP_SIZE_Y-1-j].y - field.CENTER_Y + 214));
					}
				}
				
				// двигаем влево
				if (isleft == 1)
				{
					clear();
					if (canmove(field.PlayX-1,field.PlayY))
					field.PlayX -= 1;
					isleft = 3;
				}
				
				// двигаем вправо
				if (isright == 1)
				{
					clear();
					if (canmove(field.PlayX+1,field.PlayY))
					field.PlayX += 1;
					isright = 3;
				}
				
				// поворачиваем
				if (isup == 1)
				{
					delay += 1;
					// с задержкой для красивости
					if (delay == 3)
					{
						clear();
						if (canrotate(rotat)) 
						rotat += 1;
						if (rotat == 4) rotat = 0;
						isup = 3;
						delay = 0;
					}
				}
				if (isup == 2) delay = 2;
				
				// ускоряем падение
				if (isdown == 1)
				{
					clear();
					if (canmove(field.PlayX,field.PlayY+1))
					field.PlayY += 1;
					//isdown = 3;
					endmove();
				}
					
			}
		}
		
		// центрим надписи
		private function centerTexts(): void
		{
			tex.LevelValueText.x = 390 - (tex.LevelValueText.width / 2); 
			tex.ScoreValueText.x = 390 - (tex.ScoreValueText.width / 2); 
			tex.LinesValueText.x = 390 - (tex.LinesValueText.width / 2); 
			tex.BestScoreText.x = 235 - (tex.BestScoreText.width / 2); 
		}
		
		// нажатие на кнопку старт
		private function clickStart(e: MouseEvent): void
		{
			// скрываем меню
			startButton.visible = false;
			tex.BestScoreText.visible = false;
			logo.visible = false;
			// добавляем объекты игры
			addChild(field);
			addChild(field.View);
			addChild(field.Img);
			addChild(field.ShowNext);
			addChild(tex.NextText);
			addChild(tex.LevelText);
			addChild(tex.LinesText);
			addChild(tex.ScoreText);
			addChild(tex.LevelValueText);
			addChild(tex.LinesValueText);
			addChild(tex.ScoreValueText);
			tex.NextText.visible = true;
			tex.LevelText.visible = true;
			tex.LinesText.visible = true;
			tex.ScoreText.visible = true;
			tex.LevelValueText.visible = true;
			tex.LinesValueText.visible = true;
			tex.ScoreValueText.visible = true;
			field.View.visible = true;
			field.Img.visible = true;
			field.ShowNext.visible = true;
			// переключаем на игру
			isgame = 1;
			// стартовая позиция
			field.PlayX = 3;
			field.PlayY = 0;
			rotat = 0;
			// обнуляем счётчики
			levelCount = 1;
			levelCount = 1;
			scoreCount = 0;
			linesCount = 0;
			// обновляем надписи
			tex.LevelValueText.text = String(levelCount);
			tex.ScoreValueText.text = String(scoreCount);
			tex.LinesValueText.text = String(linesCount);
			centerTexts();
			// чистим поле
			for (var i: int = 1; i < field.MAP_SIZE_X-1; i++)
			{
				for (var j: int = 1; j < field.MAP_SIZE_Y-1; j++)
					{
						field.Grid[i][j].z = 0;
					}
			}
			updateShowNext();
			// чистим битмап
			field.Img.bitmapData = new BitmapData(240, 480, true, 0x00000000);
		}
		
		// обрабатываем и записываем нажатия кнопок
		
		private function myKeyDown(event:KeyboardEvent):void
		{
			switch( event.keyCode )
			{
				case Keyboard.UP:
					isup = 1;
					break;
					
				case Keyboard.DOWN:
					isdown = 1;
					break;
					
				case Keyboard.LEFT:
					isleft = 1;
					break;
					
				case Keyboard.RIGHT:
					isright = 1;
					break;
			}	
		}
		
		private function myKeyUp(event:KeyboardEvent):void
		{
			switch( event.keyCode )
			{
				case Keyboard.UP:
					isup = 2;
					break;
					
				case Keyboard.DOWN:
					isdown = 2;
					break;
					
				case Keyboard.LEFT:
					isleft = 2;
					break;
					
				case Keyboard.RIGHT:
					isright = 2;
					break;
			}	
		}
	}
	
}