package Engine
{
	import flash.display.Bitmap;
	import flash.display.BitmapData;
	import flash.display.IBitmapDrawable;
	import flash.geom.Matrix;
	import flash.geom.Point;
	import flash.geom.Rectangle;
	/**
	 * ...
	 * @author ...
	 */
	public class GameSprite
	{
		private var _bitmap:Bitmap;
		private var _frames:Array;
		
		private var _spriteWidth:uint;
		private var _spriteHeight:uint;
		private var _spriteRect:Rectangle;
		
		private var _animated:Boolean = false;
		private var _minFrame:uint = 0;
		private var _maxFrame:uint = 0;
		private var _currentFrame:Number = 0;
		private var _frameRate:Number = 1;
		private var _playing:Boolean = true;
		
		private var _globalPosition:Point = new Point();
		private var _centerPoint:Point;
		private var _angle:Number = 0;
		private var _scaleX:Number = 1;
		private var _scaleY:Number = 1;
		
		private var _matrix:Matrix = new Matrix();
		
		public var parentEngine:SpriteEngine = null;
		public var Group:SpriteGroup = null;
		
		public var Drawed:Boolean = false;
		
		public var Delete:Boolean = false;
		
		public var zIndex:int = 0;
		
		public var CollisionEnabled:Boolean = false;
		
		/**
		 * Сеттер X
		 */
		public function set x(val:int):void {
			_globalPosition.x = val;
		}
		
		/**
		 * Геттер X
		 */
		public function get x():int {
			return _globalPosition.x;
		}
		
		/**
		 * Сеттер Y
		 */
		public function set y(val:int):void {
			_globalPosition.y = val;
		}
		
		/**
		 * Геттер Y
		 */
		public function get y():int {
			return _globalPosition.y;
		}
		
		public function get globalX():int {
			if (_spriteRect != null) {
				return _spriteRect.left;
			}else {
				return x;
			}
			
		}
		
		public function get globalY():int {
			if (_spriteRect != null) {
				return _spriteRect.top;
			}else {
				return y;
			}
			
		}
		
		public function get width():uint {
			return _spriteWidth;
		}
		
		public function get height():uint {
			return _spriteHeight;
		}
		
		public function set rotation(val:Number):void {
			_angle = val;
		}
		
		public function get rotation():Number {
			return _angle;
		}
		
		public function set scale(val:Number):void {
			_scaleX = val;
			_scaleY = val;
		}
		
		public function get scale():Number {
			return _scaleX;
		}
		
		public function get Rect():Rectangle {
			_spriteRect.width = _spriteWidth;
			_spriteRect.height = _spriteHeight;
			return _spriteRect;
		}
		
		public function get totalFrames():uint {
			return _frames.length;
		}
		
		public function set currentFrame(val:uint):void {
			if (val < totalFrames) {
				_currentFrame = val;
			}
		}
		
		public function get currentFrame():uint {
			return Math.floor(_currentFrame);
		}
		
		public function set outside(val:Boolean):void {
			return;
		}
		
		public function get outside():Boolean {
			return false;
		}
		
		/**
		 * Геттер матрицы преобразования
		 */
		public function get Translations():Matrix {
			return _matrix;
		}
		
		public function Play():void {
			_playing = true;
		}
		
		public function Stop():void {
			_playing = false;
		}
		
		public function SetAnimationRegion(frameStart:uint, frameEnd:uint):void {
			_minFrame = frameStart;
			_maxFrame = frameEnd;
		}
		
		public function ResetAnimationRegion():void {
			_minFrame = 0;
			_maxFrame = _frames.length - 1;
		}
		
		public function AnimationFinished():void {
			
		}
		
		/**
		 * Результат
		 *
		 * @return
		 */
		public function Draw(surface:BitmapData, inmatrix:Matrix = null):void {
			var result:BitmapData;
			
			// Обнуляем матрицу
			_matrix.identity();
			
			// Перемещаем так, чтобы центр спрайта оказался в нулевой точке
			_matrix.translate( -_centerPoint.x, -_centerPoint.y);
			
			// Если нужно, поворациваем
			if (_angle != 0) {
				_matrix.rotate(_angle);
			}
			
			// Если нужно, изменяем размеры
			if ((_scaleX != 1) || (_scaleY != 1)) {
				_matrix.scale(_scaleX, _scaleY);
			}
			
			// Перемещаем в нужное место
			_matrix.translate(_globalPosition.x, _globalPosition.y);
			
			// Если анимированный спрайт, анимируем
			if (_animated) {
				result = _frames[Math.floor(_currentFrame)];
				
				if (_playing) {
					_currentFrame += _frameRate;
					if (Math.floor(_currentFrame) > _maxFrame) {
						_currentFrame = _minFrame;
						AnimationFinished();
					}
				}
			}else {
				result = _bitmap.bitmapData;
			}
			
			// Если есть матрица в параметре, приплюсовываем
			if (inmatrix != null) {
				_matrix.concat(inmatrix);
			}
			
			// Рисуем
			if (result is IBitmapDrawable) {
				surface.draw(result, _matrix, null, null, null, true);
			}
			
			
			_spriteRect.left = _matrix.tx;
			_spriteRect.top = _matrix.ty;
			
			if (0) {
				
				surface.setPixel(globalX, globalY, 0x00ff00);
				
				surface.setPixel(Rect.left, Rect.top, 0xff0000);
				surface.setPixel(Rect.left + Rect.width, Rect.top, 0xff0000);
				surface.setPixel(Rect.left + Rect.width, Rect.top + Rect.height, 0xff0000);
				surface.setPixel(Rect.left, Rect.top + Rect.height, 0xff0000);
			}
			
		}
		
		public function AddedToEngine():void {}
		
		/**
		 * Двигать
		 */
		public function Move():void { }
		
		/**
		 * Вызывается, когда объект пересекается с другим объектом
		 * @param	Intersects Объект с которым произошло столкновение
		 */
		public function Collision(Intersects:GameSprite):void { }
		
		/**
		 * Конструктор
		 *
		 * @param	spriteBmp	Битмап со спрайтом
		 * @param	animated	Является ли этот спрайт анимированным
		 * @param	frameWidth	Ширина кадра
		 * @param	frameHeight	Высота кадра
		 * @param	frameRate	Относительная частота кадров
		 */
		public function GameSprite(spriteBmp:Bitmap, rotationCenter:Point, animated:Boolean = false, frameWidth:uint = 0, frameHeight:uint = 0, frameRate:Number = 1)
		{
			if (spriteBmp == null) {
				return;
			}
			
			_bitmap = spriteBmp;
			_matrix = new Matrix();
			
			_centerPoint = rotationCenter;
			
			_animated = animated;
			
			if (animated) {
				_spriteWidth = frameWidth;
				_spriteHeight = frameHeight;
				_frameRate = frameRate;
				
				_frames = new Array();
				
				for (var j:uint = 0; j < Math.floor(_bitmap.height / frameHeight); j++) {
					for (var i:uint = 0; i < Math.floor(_bitmap.width / frameWidth); i++) {
						var _frameData:BitmapData = new BitmapData(frameWidth, frameHeight);
						_frameData.copyPixels(_bitmap.bitmapData, new Rectangle(i * frameWidth, j * frameHeight, frameWidth, frameHeight), new Point(0, 0));
						_frames[_frames.length] = _frameData;
					}
				}
				
				ResetAnimationRegion();
				
			}else {
				_spriteWidth = _bitmap.width;
				_spriteHeight = _bitmap.height;
			}
			
			_spriteRect = new Rectangle(0, 0, _spriteWidth, _spriteHeight);
		}
		
	}

}