
package {
	import com.netgrind.core.Utils;
	import flash.display.Bitmap;
	import flash.display.Sprite;
	import flash.geom.Point;
	import flash.ui.Keyboard;
	import nape.callbacks.CbEvent;
	import nape.callbacks.InteractionCallback;
	import nape.callbacks.InteractionListener;
	import nape.callbacks.InteractionType;
	import nape.geom.Vec2;
	import nape.phys.Body;
	import nape.phys.BodyType;
	import nape.phys.Material;
	import nape.shape.Circle;
	import nape.space.Space;
	import com.netgrind.core.Key;
	import com.netgrind.core.Scheduler;
	/**
	 * ...
	 * @author netgrind
	 */
	public class Car extends Sprite{
	
		[Embed(source = "../lib/car_wattcar.png")]private static var texture:Class;
		private var leftPressed:Boolean;
		private var rightPressed:Boolean;
		
		public var body:Body;
		
		public var size:Number = 30;
		
		public var acceleration:Number = 20;
		public var maxSpeed:Number = 400;//pixels per second
		public var turnSpeed:Number = .1;
		public var speed:Number = 0;
		public var torque:Number = 0;
		public var drag:Number = .9;
		public var drift:Number = .9;
		
		public var forward:Vec2 = new Vec2();
		public var right:Vec2 = new Vec2();
		
		public var cameraTarget:Point = new Point();
		public var bitmap:FaceSprite;
		public var turnVelocity:Number = 0;
		public var turnAccel:Number = 0.2;
		private var _damage:int = 0;
		public var damageCooldown:Number = 0;
		public var pause:Boolean = false;
		
		public function Car(space:Space, position:Vec2 ) {
			super();
			bitmap = new FaceSprite(new texture(),135);
			bitmap.width *= 0.55;
			bitmap.height *= 0.55;
			addChild(bitmap);			
			
			body = new Body(BodyType.DYNAMIC, position);
			body.space = space;
			body.shapes.add(new Circle(size * .5,new Vec2(0,0)));			
			body.setShapeMaterials(new Material(0, 0, 0, 1, 0));
			body.cbTypes.add(Level.carCollisionType);
			Key.bindFunctionToKeyHold(up, Keyboard.W);
			Key.bindFunctionToKeyHold(up, Keyboard.UP);
			Key.bindFunctionToKeyHold(down, Keyboard.S);
			Key.bindFunctionToKeyHold(down, Keyboard.DOWN);
			Scheduler.invokeIn(Scheduler.invokeEvery, 1, update);
			
			var interaction:InteractionListener = new InteractionListener(CbEvent.BEGIN, InteractionType.COLLISION, Level.carCollisionType, Level.wallCollisionType, onCollide);
			space.listeners.add(interaction);
		}
		
		public function onCollide(col:InteractionCallback):void {
			if (damageCooldown > 0) return;
			if (col.arbiters.at(0).totalImpulse().length > 80) {
				damage++;
				damageCooldown = 30;
			}
		}
		
		public function update():void {
			if (pause) return;
			if (damageCooldown > 0) {
				damageCooldown -= Scheduler.deltaTime;
				alpha = Math.sin(damageCooldown*10)*.5+.5;
			}else {
				alpha = 1;
			}
			
			forward.x = Math.cos(body.rotation);
			forward.y = Math.sin(body.rotation);
			right.x = Math.cos(body.rotation-Math.PI*.5);
			right.y = Math.sin(body.rotation-Math.PI*.5);
			
			var fwd:Vec2 = forward.mul(body.velocity.dot(forward));
			var side:Vec2 = right.mul(body.velocity.dot(right));
			
			body.velocity = fwd.add(side.mul(drift));
			
			body.angularVel = 0;
			body.velocity.x += Math.cos(body.rotation) * torque;
			body.velocity.y += Math.sin(body.rotation) * torque;
			torque = 0;
			speed = body.velocity.length;
			if (speed > maxSpeed) {
				body.velocity = body.velocity.normalise().mul(maxSpeed);
			}		
			
			leftPressed = (Key.pressed(Keyboard.A) || Key.pressed(Keyboard.LEFT));
			rightPressed = (Key.pressed(Keyboard.D) || Key.pressed(Keyboard.RIGHT));
			if (rightPressed) {
				turnVelocity += turnAccel;
				turnVelocity = Math.min(1, turnVelocity);
			}else if(!leftPressed)turnVelocity = Math.min(0, turnVelocity);
			if (leftPressed) {
				turnVelocity -= turnAccel;
				turnVelocity = Math.max(-1, turnVelocity);
			}else if(!rightPressed)turnVelocity = Math.max(0, turnVelocity);
			
			body.rotation += Math.min(body.velocity.length * .01, 1) * turnVelocity * turnSpeed * Scheduler.deltaTime*Scheduler.timeScale;	
			this.rotation = Utils.radToDeg(body.rotation);
			
			cameraTarget.x = body.position.x + body.velocity.x * .5*Scheduler.timeScale;
			cameraTarget.y = body.position.y + body.velocity.y * .5 * Scheduler.timeScale;
		}
		public function updatePosition():void {
			x = body.position.x;
			y = body.position.y;
		}
		public function turnRight():void {
			turnVelocity -= turnAccel;
			turnVelocity = Math.max(-1, turnVelocity);
		}
		
		public function down():void {
			torque = -acceleration*.5*Scheduler.deltaTime;			
		}
		
		public function up():void {
			torque = acceleration*Scheduler.deltaTime;
		}
		
		public function repair():void {
			if(damage>0){
				body.velocity.setxy(0, 0);
				damage--;
				Scheduler.invokeInMS(repair, 500);
				pause = true;
			}else {
				pause = false;
			}
		}
		
		public function get damage():int {
			return _damage;
		}
		
		public function set damage(value:int):void {
			_damage = Math.min(4,value);
			bitmap.displayFrame(_damage);
		}
		
	}
	
}