package game.projectiles 
{
	import com.cheezeworld.math.Vector2D;
	import events.ImpactEvent;
	import events.ModelEvent;
	import flash.events.Event;
	import game.enemies.Enemy;
	import game.models.Model;
	import game.models.MovingModel;
	import game.towers.Tower;
	import utils.ModelUtilities;
	/**
	 * ...
	 * @author 
	 */
	public class Projectile extends MovingModel {
		static public const ON_HIT:String = "onHit";
		
		protected var _target:Enemy;
			public function get target():Enemy { return _target; }
		protected var _damage:int;
			public function get damage():int { return _damage; }
		protected var _shooter:Tower;
			public function get shooter():Tower { return _shooter; }
		
		protected var _positionToMove:Vector2D;
		
		protected var removeOnTargetDeath:Boolean;
		protected var maxtravelFrames:int;
		private var currentTravelFrame:int;
		
		public function Projectile(shooter:Tower, target:Enemy) {
			super();
			_target = target;
			_shooter = shooter;
			_damage = shooter.damage;
			maxtravelFrames = 12;
			currentTravelFrame = 0;
			
			_position.x = shooter.position.x;
			_position.y = shooter.position.y;
			removeOnTargetDeath = true;
			
			_target.addEventListener(Model.DISPOSE, onTargetDispose);
			
			upgradeStats();
		}
		
		override public function update():void {
			currentTravelFrame++;
			applyVelocity();
			
			if (_target != null && _target.position) {
				velocity.x = ((_target.position.x - _position.x) / maxtravelFrames) * currentTravelFrame;
				velocity.y = ((_target.position.y - _position.y) / maxtravelFrames) * currentTravelFrame;
				
				if ( checkTargetCollision(_target) ) {
					onHitTarget();
				}
			} else if ( !removeOnTargetDeath && _positionToMove != null) {
				velocity.x = ((_positionToMove.x - _position.x) / maxtravelFrames) * currentTravelFrame;
				velocity.y = ((_positionToMove.y - _position.y) / maxtravelFrames) * currentTravelFrame;
				
				if (currentTravelFrame == maxtravelFrames) {
					onHitDestination();
				}
			} else {
				dispatchEvent( new ModelEvent(ON_HIT, this) );
			}
		}
		
		protected function upgradeStats():void {
			//abstract
		}
		
		private function onTargetDispose(e:Event):void {
			_positionToMove = _target.position.copy();
		}
		
		//Gets called instead of OnHitTarget if the target is killed before this projectile gets to its destination
		protected function onHitDestination():void {
			dispatchEvent( new ModelEvent(ON_HIT, this) );
		}
		
		protected function onHitTarget():void {
			_target.onImpact(_damage);
			dispatchEvent( new ModelEvent(ON_HIT, this) );
		}
		
		protected function checkTargetCollision(target:Enemy):Boolean {
			var distance:Number = ModelUtilities.getRadiusDistance(this, target);
			
			if (distance < target.radius) 	return true;
			else 							return false;
		}
		
		override public function dispose():void {
			super.dispose();
			
			_target.removeEventListener(Model.DISPOSE, onTargetDispose);
		}
	}

}