package {

	import away3d.cameras.HoverCamera3D;
	import away3d.containers.View3D;
	
	import com.techlabs.puzzle.ControlPanel;
	import com.techlabs.puzzle.PuzzleBoard;
	import com.techlabs.puzzle.events.PuzzleEvent;
	import com.techlabs.puzzle.helpers.ImageSlicer;
	
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.display.Sprite;
	import flash.display.StageAlign;
	import flash.display.StageQuality;
	import flash.display.StageScaleMode;
	
	import flash.events.Event;
	import flash.net.URLRequest;
	
	/**
	 * ...
	 * @author Timo Virtanen
	 */
	[SWF(width=800, height = 600, backgroundColor = "#333333", framerate = "25")]
	public class SlidingPuzzle extends Sprite {
		
		// Defines how the puzzle will be divided
		public static var subdivisions:int = 4;
		
		// Padding between the pieces
		public static var padding:int = 2;
		
		// The size of the puzzle board
		public static var size:int = 500;

		private var _image:Bitmap;

		private var _loader:Loader;
		private var _request:URLRequest;
		
		private var _slicer:ImageSlicer;
		private var _puzzleImages:Array;

		private var _gameBoard:PuzzleBoard;

		private var _view:View3D;
		private var _camera:HoverCamera3D;

		private var _controlPanel:ControlPanel;

		public function SlidingPuzzle() {
			_slicer = new ImageSlicer();

			_gameBoard = new PuzzleBoard();
			_puzzleImages = new Array();

			_controlPanel = new ControlPanel();
			_controlPanel.addEventListener(PuzzleEvent.CHANGE_IMAGE, imageChangeHandler);
			_controlPanel.addEventListener(PuzzleEvent.SHUFFLE, suffleHandler);
			addChild(_controlPanel);

			initStage();
			init3D();

			initPuzzle("assets/Puzzle_Flash.png");
		}

		private function initStage():void {
			stage.align = StageAlign.TOP_LEFT;
			stage.quality = StageQuality.MEDIUM;
			stage.scaleMode = StageScaleMode.NO_SCALE;
		}

		private function init3D():void {
			_camera = new HoverCamera3D();
			_camera.mintiltangle = 15;
			_camera.maxtiltangle = 65;

			_view = new View3D({width:800, height:600, x:400, y:300, camera:_camera});
			addChild(_view);

			addEventListener(Event.ENTER_FRAME, enterFrameHandler);
		}

		private function initPuzzle(imageURL:String):void {
			loadPuzzleImage(imageURL);
		}
		
		// Loads the image
		private function loadPuzzleImage(imageURL:String):void {
			_loader = new Loader();
			_request = new URLRequest(imageURL);
			_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, imageLoadComplete);
			_loader.load(_request);
		}
		
		// This will execute when load completes
		private function imageLoadComplete(e:Event):void {
			_image = _loader.content as Bitmap;
			
			// sliceImage() returns a two dimensional array containing the sliced bitmaps
			_puzzleImages = _slicer.sliceImage(_image);
			
			// creates the puzzle board
			_gameBoard.createPuzzle(_puzzleImages);
			_view.scene.addChild(_gameBoard);
			
			// sets the preview image in the control panel
			_controlPanel.setPreview(_image);
		}

		private function imageChangeHandler(e:PuzzleEvent):void {
			initPuzzle(e.imageURL);
		}
		
		private function suffleHandler(e:PuzzleEvent):void {
			_gameBoard.shuffle();
		}
		
		// EnterFrameHandler is responsible for
		// 1. camera controls
		// 2. rendering the 3D view
		private function enterFrameHandler(e:Event):void {
			_camera.targetpanangle = (stage.stageWidth * .5 - stage.mouseX) * .1 - 180;
			_camera.targettiltangle = (stage.stageHeight * .5 - stage.mouseY) * .5;
			_camera.hover();
			
			_view.render();
		}

	}

}
