package game
{
	import interf.IGameElm;
	import flash.display.BitmapData;
	import flash.geom.Rectangle;
	import flash.geom.Point;
	import sound.DownSound;
	import sound.JumpSound;
	import sound.FlySound;
	import ui.GameSound;
	import flash.display.Bitmap;
	import flash.display.DisplayObjectContainer;
	import vo.gameTime;
	import vo.frameDelay;
	import vo.Mem;
	
	public class Panda extends Object implements IGameElm
	{
		
		public function Panda()
		{
			this.physicsHiter = this.runHiter;
			this.prev = new Point();
			this.updateBitmapData = this.runFrame;
			this.fastEff = new Bitmap();
			this.flyEffBmp = new Bitmap();
			super();
		}
		
		public static const sp:int = 1000;
		
		private static var PandaBmp:Class = Panda_PandaBmp;
		
		private static var SpeedEffBmp:Class = Panda_SpeedEffBmp;
		
		public static const speedEffSrc:BitmapData = new SpeedEffBmp().bitmapData;
		
		private static var FlyEffBmp:Class = Panda_FlyEffBmp;
		
		public static const flyEffSrc:BitmapData = new FlyEffBmp().bitmapData;
		
		private static var runBmpds:Vector.<BitmapData>;
		
		private static var jumpBmpds:Vector.<BitmapData>;
		
		private static var somersaultBmpds:Vector.<BitmapData>;
		
		private static var flyBmpds:Vector.<BitmapData>;
		
		private static var bombBmpds:Vector.<BitmapData>;
		
		private static var rollBmpds:Vector.<BitmapData>;
		
		private static var speedEffBmpds:Vector.<BitmapData>;
		
		private static var flyEffBmpds:Vector.<BitmapData>;
		
		private static var bruiseBmpds:Vector.<BitmapData>;
		
		private static var fastBmpds:Vector.<BitmapData>;
		
		public static function init():void
		{
			var bmpd:BitmapData = null;
			var i:* = 0;
			var src:BitmapData = new PandaBmp().bitmapData;
			runBmpds = new Vector.<BitmapData>();
			jumpBmpds = new Vector.<BitmapData>();
			somersaultBmpds = new Vector.<BitmapData>();
			flyBmpds = new Vector.<BitmapData>();
			bombBmpds = new Vector.<BitmapData>();
			rollBmpds = new Vector.<BitmapData>();
			speedEffBmpds = new Vector.<BitmapData>();
			flyEffBmpds = new Vector.<BitmapData>();
			bruiseBmpds = new Vector.<BitmapData>();
			fastBmpds = new Vector.<BitmapData>();
			var rect:Rectangle = new Rectangle(0, 0, 79, 93);
			var point:Point = new Point();
			rect.width = 99;
			rect.height = 84;
			i = 0;
			while (i < 4)
			{
				rect.x = rect.width * i;
				bmpd = new BitmapData(99, 84);
				bmpd.copyPixels(flyEffSrc, rect, point);
				flyEffBmpds.push(bmpd);
				i++;
			}
			rect.width = 79;
			rect.height = 93;
			i = 0;
			while (i < 4)
			{
				rect.x = rect.width * i;
				bmpd = new BitmapData(rect.width, rect.height);
				bmpd.copyPixels(speedEffSrc, rect, point);
				speedEffBmpds.push(bmpd);
				i++;
			}
			i = 0;
			while (i < 8)
			{
				bmpd = new BitmapData(rect.width, rect.height);
				rect.x = rect.width * i;
				bmpd.copyPixels(src, rect, point);
				runBmpds.push(bmpd);
				i++;
			}
			rect.y = rect.height;
			i = 0;
			while (i < 8)
			{
				bmpd = new BitmapData(rect.width, rect.height);
				rect.x = rect.width * i;
				bmpd.copyPixels(src, rect, point);
				jumpBmpds.push(bmpd);
				i++;
			}
			rect.y = rect.height * 2;
			i = 0;
			while (i < 8)
			{
				bmpd = new BitmapData(rect.width, rect.height);
				rect.x = rect.width * i;
				bmpd.copyPixels(src, rect, point);
				somersaultBmpds.push(bmpd);
				i++;
			}
			rect.y = rect.height * 3;
			i = 0;
			while (i < 8)
			{
				bmpd = new BitmapData(rect.width, rect.height);
				rect.x = rect.width * i;
				bmpd.copyPixels(src, rect, point);
				flyBmpds.push(bmpd);
				i++;
			}
			rect.y = rect.height * 4;
			i = 0;
			while (i < 8)
			{
				bmpd = new BitmapData(rect.width, rect.height);
				rect.x = rect.width * i;
				bmpd.copyPixels(src, rect, point);
				bombBmpds.push(bmpd);
				i++;
			}
			rect.y = rect.height * 5;
			i = 0;
			while (i < 8)
			{
				bmpd = new BitmapData(rect.width, rect.height);
				rect.x = rect.width * i;
				bmpd.copyPixels(src, rect, point);
				rollBmpds.push(bmpd);
				i++;
			}
			rect.y = rect.height * 6;
			i = 0;
			while (i < 8)
			{
				bmpd = new BitmapData(rect.width, rect.height);
				rect.x = rect.width * i;
				bmpd.copyPixels(src, rect, point);
				bruiseBmpds.push(bmpd);
				i++;
			}
			rect.y = rect.height * 7;
			i = 0;
			while (i < 8)
			{
				bmpd = new BitmapData(rect.width, rect.height);
				rect.x = rect.width * i;
				bmpd.copyPixels(src, rect, point);
				fastBmpds.push(bmpd);
				i++;
			}
			src.dispose();
			src = null;
		}
		
		public static const standSound:DownSound = new DownSound();
		
		public static const jumpSound:JumpSound = new JumpSound();
		
		public static const flySound:FlySound = new FlySound();
		
		public var numBamboo:int;
		
		public var numShoots:int = 3;
		
		public var strongFast:int = -10000;
		
		public var strongJump:int = -5000;
		
		public var mallShoots:int;
		
		public var numMilk:int = 3;
		
		public var numAmulet:int;
		
		public var sp:Number = 1000;
		
		public var consumption:int;
		
		public const rect:Rectangle = new Rectangle(0, 0, 79, 92);
		
		public const speed:Point = new Point(500, 0);
		
		public var board:Board;
		
		public var enemy:Enemy;
		
		public var food:Food;
		
		public var shoots:game.Shoots;
		
		public var sound1:GameSound;
		
		public var data:Data;
		
		public var ground:Ground;
		
		public var scene:Scene;
		
		private var physicsHiter:Function;
		
		public const dpo:Bitmap = new Bitmap();
		
		private var _max:int = 1;
		
		public function get max():int
		{
			return this._max;
		}
		
		public function allStep():void
		{
			this.step();
		}
		
		public function init(board:Board, food:Food, enemy:Enemy, shoots:game.Shoots, ground:Ground, scene:Scene):void
		{
			this.board = board;
			this.food = food;
			this.enemy = enemy;
			this.shoots = shoots;
			this.ground = ground;
			this.scene = scene;
			this.dpo.bitmapData = runBmpds[0];
			this.dpo.visible = false;
		}
		
		public var nearMiss:Boolean;
		
		private var startX:int;
		
		public function start():void
		{
			this.dpo.visible = true;
			this.dpo.y = this.rect.y = this.board.rect.y - this.rect.height;
			this.dpo.x = this.startX = this.rect.x = this.board.rect.x;
			this.somersaulting = false;
			this.physicsHiter = this.runHiter;
			this.updateBitmapData = this.runFrame;
			this.sp = Panda.sp;
			this.strongFast = -10000;
			this.strongJump = -5000;
			this.lockCtrlTime = -500;
			this.numHits = 0;
			this.eatBamboo = 0;
			this.eatShoots = 0;
			this.nearMiss = false;
			this.shaking = false;
			this.a_down = false;
			this.bombing = false;
			this.bruising = false;
			this.speed.y = 0;
			this.speed.x = this.xsc;
		}
		
		public function get runningDistance():int
		{
			return (this.rect.x - this.startX) / 50;
		}
		
		public function showAs(dpoc:DisplayObjectContainer):void
		{
			dpoc.addChild(this.dpo);
			dpoc.addChild(this.flyEffBmp);
			dpoc.addChild(this.fastEff);
		}
		
		public function step():void
		{
			this.running();
			this.physicsHiter();
			this.foodHiter();
			this.enemyHiter();
			this.updateView();
			this.effView();
		}
		
		private var prev:Point;
		
		private var acc:Number = 2000;
		
		private var shakePre:Number;
		
		private var shaking:Boolean;
		
		private var shakeY:Number;
		
		private function shake():void
		{
			this.shaking = true;
			this.shakePre = 0;
			this.shakeY = this.rect.y;
		}
		
		private var xacc:int = 200;
		
		private var xsc:int = 500;
		
		private var xasc:int = 800;
		
		private var fasting:Boolean;
		
		private var _lastTx:int;
		
		private function running():void
		{
			if (this.bombing)
			{
				return;
			}
			this.fasting = gameTime - this.strongFast < 10000;
			if (!this.fasting)
			{
				this.ground.normal();
			}
			var tx:int = this.fasting ? this.xasc : this.xsc;
			tx = tx + int(gameTime / 20000) * 20;
			if (tx < this.speed.x)
			{
				this.speed.x = this.speed.x - this.xacc * frameDelay;
				if (tx > this.speed.x)
				{
					this.speed.x = tx;
				}
			}
			else
			{
				this.speed.x = tx;
			}
			this.prev.x = this.rect.x;
			this.rect.x = this.prev.x + frameDelay * this.speed.x;
			if (tx != this._lastTx)
			{
				this._lastTx = tx;
				this.scene.speedUp(this.rect.x + 500);
			}
		}
		
		private function runHiter():void
		{
			if (this.sp < Panda.sp)
			{
				this.sp = this.sp + frameDelay * 50;
				if (this.sp > Panda.sp)
				{
					this.sp = Panda.sp;
				}
			}
			if (this.rect.x > this.board.rect.right)
			{
				this.physicsHiter = this.fallHiter;
			}
			else if (this.shaking)
			{
				if (this.shakePre < Math.PI)
				{
					this.shakePre = Math.min(Math.PI, this.shakePre + 0.35);
					this.rect.y = this.shakeY + 15 * Math.sin(this.shakePre);
				}
				else
				{
					this.shaking = false;
				}
			}
		
		}
		
		private function fallHiter():void
		{
			this.falling();
			this.flyDetector();
			this.boardHiter();
			this.autoItems();
		}
		
		private function flyHiter():void
		{
			if (this.sp > 0)
			{
				this.sp = this.sp + frameDelay * -200;
				if (this.sp < 0)
				{
					this.sp = 0;
					this.sound1.stopFlySound();
					this.physicsHiter = this.fallHiter;
					return;
				}
				var power:int = 0;
				if (gameTime - this.strongJump < 5000)
				{
					power = -50;
				}
				if (this.speed.y == power - 250)
				{
					this.rect.y = this.prev.y + this.speed.y * frameDelay;
					this.prev.y = this.rect.y;
				}
				else
				{
					this.speed.y = this.speed.y - 100;
					if (this.speed.y < power - 250)
					{
						this.speed.y = power - 250;
						this.flyHiter();
					}
					else
					{
						this.falling();
						this.boardHiter();
					}
				}
				return;
			}
			this.sound1.stopFlySound();
			this.physicsHiter = this.fallHiter;
		}
		
		private function falling():void
		{
			this.prev.y = this.rect.y;
			this.speed.y = this.speed.y + this.acc * frameDelay;
			this.rect.y = this.prev.y + this.speed.y * frameDelay;
		}
		
		private function boardHiter():void
		{
			var i:int = 0;
			while (i < Mem.numBoards)
			{
				if ((this.rect.bottom > this.board.rect.top) && (this.prev.y + this.rect.height <= this.board.rect.top) && (this.rect.right > this.board.rect.left) && (this.rect.left < this.board.rect.right))
				{
					return this.stand();
				}
				this.board = this.board.next;
				i++;
			}
		}
		
		private function foodHiter():void
		{
			var i:int = 0;
			while (i < Mem.numFoods)
			{
				if ((!this.food.isEated) && (this.rect.intersects(this.food.rect)))
				{
					return this.eating();
				}
				this.food = this.food.next;
				i++;
			}
		}
		
		private function enemyHiter():void
		{
			var i:int = 0;
			while (i < Mem.numEnemys)
			{
				if ((!this.enemy.isBruised) && (this.rect.intersects(this.enemy.rect)))
				{
					return this.bruise();
				}
				this.enemy = this.enemy.next;
				i++;
			}
		}
		
		public var eatBamboo:int;
		
		public var eatShoots:int;
		
		private function eating():void
		{
			this.food.eat();
			switch (this.food.type)
			{
				case Food.Bamboo: 
					this.numBamboo++;
					this.eatBamboo++;
					break;
				case Food.Shoots: 
					this.numShoots++;
					this.eatShoots++;
					break;
				case Food.Mushroom: 
					this.sp = Math.min(this.sp + 200, Panda.sp);
					break;
				case Food.StrongFast: 
					this.strongFast = gameTime;
					this.blur();
					break;
				case Food.StrongJump: 
					this.strongJump = gameTime;
					break;
			}
		}
		
		private function blur():void
		{
			this.ground.bulr();
		}
		
		private function bruise():void
		{
			this.enemy.bruise();
			switch (this.enemy.type)
			{
				case Enemy.Snake: 
				case Enemy.Raven: 
					this.bruise2();
					break;
				case Enemy.Bomb: 
					this.bomb();
					break;
			}
		}
		
		private var bruising:Boolean;
		
		private var cacheUpdateFrame:Function;
		
		private var lockCtrlTime:int;
		
		private function bruise2():void
		{
			if (this.sp > 100)
			{
				this.sp = 100;
			}
			this.bruising = true;
			this.startTime = gameTime;
			this.lockCtrlTime = gameTime;
			this.cacheUpdateFrame = this.updateBitmapData;
			this.updateBitmapData = this.bruiseFrame;
		}
		
		private var bombing:Boolean;
		
		private function bomb():void
		{
			this.bombing = (this.numAmulet < 1);
			if (this.numAmulet < 1)
			{
				this.startTime = gameTime;
				this.speed.y = -500;
				this.physicsHiter = this.falling;
				this.updateBitmapData = this.bombFrame;
			}
			else
			{
				this.data.amulet = --this.numAmulet;
				this.data.save();
			}
		}
		
		public function isRunning():Boolean
		{
			return this.physicsHiter == this.runHiter;
		}
		
		public function isFalling():Boolean
		{
			return this.physicsHiter == this.fallHiter;
		}
		
		private function stand():void
		{
			this.physicsHiter = this.runHiter;
			this.somersaulting = false;
			if (this.updateBitmapData == this.bruiseFrame)
			{
				this.cacheUpdateFrame = this.runFrame;
			}
			else if (this.speed.y > 1000)
			{
				this.startTime = gameTime;
				this.updateBitmapData = this.rollFrame;
			}
			else
			{
				this.updateBitmapData = this.runFrame;
			}
			
			this.speed.y = 0;
			this.rect.y = this.board.rect.y - this.rect.height;
			this.shake();
			this.board.shake();
			standSound.play();
		}
		
		public var smoke:Smoke;
		
		public function jump():void
		{
			jumpSound.play();
			var power:int = 0;
			if (gameTime - this.strongJump < 5000)
			{
				power = -200;
			}
			this.physicsHiter = this.fallHiter;
			this.speed.y = power - 880;
			this.startTime = gameTime;
			this.updateBitmapData = this.jumpFrame;
			this.smoke.show(this.rect.x, this.rect.bottom);
		}
		
		private var somersaulting:Boolean;
		
		public function get willFly():Boolean
		{
			return this.somersaulting;
		}
		
		public function somersault():void
		{
			jumpSound.play();
			var power:int = 0;
			if (gameTime - this.strongJump < 5000)
			{
				power = -200;
			}
			this.speed.y = power - 800;
			this.startTime = gameTime;
			this.somersaulting = true;
			this.updateBitmapData = this.somersaultFrame;
		}
		
		private function flyDetector():void
		{
			if ((this.a_down) && (this.somersaulting) && (gameTime - this.startTime > 600))
			{
				this.fly();
			}
		}
		
		public function get flying():Boolean
		{
			return this.physicsHiter == this.flyHiter;
		}
		
		public function fly():void
		{
			if (this.sp > 0)
			{
				this.sound1.playFlySound();
				this.physicsHiter = this.flyHiter;
				this.updateBitmapData = this.flyFrame;
			}
			else
			{
				this.sound1.stopFlySound();
			}
		}
		
		public function unfly():void
		{
			this.sound1.stopFlySound();
			this.physicsHiter = this.fallHiter;
		}
		
		public function get isGongfu():Boolean
		{
			return this.updateBitmapData == this.flyFrame;
		}
		
		private function autoItems():void
		{
			if ((this.sp < 50) && (this.numMilk > 0))
			{
				this.sp = this.sp + 500;
				this.data.milk = --this.numMilk;
				this.data.save();
			}
		}
		
		public function get shooting():Boolean
		{
			var shoots:Shoots = this.shoots;
			var i:int = 0;
			while (i < Mem.numShoots)
			{
				if (shoots.running)
				{
					return true;
				}
				shoots = shoots.next;
				i++;
			}
			return false;
		}
		
		public var numHits:int;
		
		public function shoot():void
		{
			var hasTarget:Boolean = false;
			var i:int = 0;
			while (i < Mem.numEnemys)
			{
				if (this.enemy.rect.x > this.rect.x)
				{
					this.shoots.start(this, this.enemy);
					this.shoots = this.shoots.next;
					hasTarget = true;
					this.numHits++;
					return;
				}
				this.enemy = this.enemy.next;
				i++;
			}
			if (!hasTarget)
			{
				this.shoots.start(this);
				this.shoots = this.shoots.next;
			}
		}
		
		private var _disctrl:Boolean;
		
		public function set disctrl(value:Boolean):void
		{
			this._disctrl = value;
		}
		
		public function get disctrl():Boolean
		{
			return (this._disctrl) || (this.bombing) || (gameTime < this.lockCtrlTime + 350);
		}
		
		public function a():void
		{
			if (this.disctrl)
			{
				return;
			}
			this.a_down = true;
			if (this.physicsHiter == this.runHiter)
			{
				this.jump();
			}
			else if (this.somersaulting)
			{
				this.fly();
			}
			else
			{
				this.somersault();
			}
		
		}
		
		public var leftEnemy:Enemy;
		
		public function b():void
		{
			if (this.disctrl)
			{
				return;
			}
			if (this.numShoots > 0)
			{
				this.numShoots--;
				this.shoot();
			}
		}
		
		private var a_down:Boolean;
		
		public function ca():void
		{
			this.a_down = false;
			if (this.physicsHiter == this.flyHiter)
			{
				this.unfly();
			}
		}
		
		public function cb():void
		{
		}
		
		private var frameBmpds:Vector.<BitmapData>;
		
		private var updateBitmapData:Function;
		
		private function updateView():void
		{
			this.updateBitmapData();
			this.dpo.x = this.rect.x;
			this.dpo.y = this.rect.y;
		}
		
		private function runFrame():void
		{
			var bmpds:Vector.<BitmapData> = this.fasting ? fastBmpds : runBmpds;
			this.dpo.bitmapData = bmpds[int(gameTime / 50) % 8];
		}
		
		private var startTime:int;
		
		private function jumpFrame():void
		{
			var frame:int = (gameTime - this.startTime) / 83.3;
			frame = Math.max(0, Math.min(int(frame), 7));//add by LayaFlash, 需要整数时强制转换
			this.dpo.bitmapData = jumpBmpds[frame];
		}
		
		private function somersaultFrame():void
		{
			var frame:int = (gameTime - this.startTime) / 83.3;
			this.dpo.bitmapData = somersaultBmpds[Math.min(int(frame), 7)];//add by LayaFlash, 需要整数时强制转换
		}
		
		private function flyFrame():void
		{
			this.dpo.bitmapData = flyBmpds[int(gameTime / 25) % 8];//add by LayaFlash, 需要整数时强制转换
		}
		
		private function rollFrame():void
		{
			var frame:int = (gameTime - this.startTime) / 83.3;
			this.dpo.bitmapData = rollBmpds[Math.min(int(frame), 7)];//add by LayaFlash, 需要整数时强制转换
			if (frame > 7)
			{
				this.updateBitmapData = this.runFrame;
			}
		}
		
		private function bombFrame():void
		{
			var frame:int = (gameTime - this.startTime) / 83.3;
			this.dpo.bitmapData = bombBmpds[Math.min(int(frame), 7)];//add by LayaFlash, 需要整数时强制转换
			if (frame > 7)
			{
				return;
			}
		}
		
		private function bruiseFrame():void
		{
			var frame:int = (gameTime - this.startTime) / 50;
			this.dpo.bitmapData = bruiseBmpds[Math.min(int(frame), 7)];//add by LayaFlash, 需要整数时强制转换
			if (frame > 7)
			{
				this.updateBitmapData = this.cacheUpdateFrame;
			}
		}
		
		private var fastEff:Bitmap;
		
		private var flyEffBmp:Bitmap;
		
		private function effView():void
		{
			var frame:int = int(gameTime / 83.3) % 4;//add by LayaFlash, 需要整数时强制转换
			this.fastEff.bitmapData = speedEffBmpds[int(frame)];
			this.fastEff.x = this.rect.x - 30;
			this.fastEff.y = this.rect.y;
			this.fastEff.visible = this.fasting;
			this.flyEffBmp.bitmapData = flyEffBmpds[int(gameTime / 83.3) % 4];//add by LayaFlash, 需要整数时强制转换
			this.flyEffBmp.x = this.rect.x - 10;
			this.flyEffBmp.y = this.rect.y + 4;
			this.flyEffBmp.visible = this.updateBitmapData == this.flyFrame;
		}
		
		public function over():void
		{
		}
	}
}
