package ei.game.scene.weapons;

import ei.engine.effects.Particles;
import ei.engine.math.Vector2f;
import ei.engine.math.Vector2i;
import ei.engine.scene.Entity;
import ei.game.gamestate.InGameState;
import ei.game.scene.Map;
/**
 * The weapon class.
 * @author Jesper Lundin
 *
 */

public abstract class Weapon {
	private int range;
	private int damage;
	private Vector2i target;
	private float velocity;
	private float minVelocity;
	private boolean hit;
	private Particles part;
	private Vector2f startPos;
	private int reload;
	
	
	/**
	 * Constructor for the class Weapon. Initializes the weapon.
	 * @param range
	 * @param startPos
	 * @param velocity
	 */
	public Weapon(Vector2f startPos) {
		this.startPos = startPos;
		this.minVelocity = 10;
		this.hit = false;
		part = getWeapon();
		part.setLocation(startPos);
		part.reset();
	}
	
	public void setRange(int range) {
		this.range = range;
	}
	
	public void setVelocity(float velocity) {
		this.velocity = velocity;
	}
	
	public void setDamage(int damage) {
		this.damage = damage;
	}
	
	public int getDamage() {
		return this.damage;
	}
	
	public void setReload(int r){
		reload = r;
	}
	
	public int getReload(){
		return reload;
	}
	
	/**
	 * Launches the weapon type.
	 * @param target
	 */
	public void launch(Vector2i target) {
		this.target = target;		
	}
	
	/**
	 * Returns true if the wepon is on range else false
	 * @param vect The position to attack
	 * @return True if the wepon is on range else false
	 */
	public boolean onRange(Vector2f vect){
		return Math.sqrt(Math.pow((vect.getX()-startPos.getX()), 2) + Math.pow((vect.getY()-startPos.getY()), 2))<=range;
	}
	
	/**
	 * updates the weapons movement and positions, also the behaviour of
	 * the weapon.
	 *
	 */
	public void update() {
		Vector2f vect = Map.getPixelByPos(target.getX(), target.getY());
		
		if(onRange(vect)) {
			float yVelocity = (Math.abs((vect.getY()-startPos.getY()) / velocity))/10;
			float xVelocity = (Math.abs((vect.getX()-startPos.getX()) / velocity))/10;

			//System.out.println("xVel: "+Math.abs(part.getLocation().getX()-vect.getX()));
			if(xVelocity < minVelocity && xVelocity > yVelocity) {
				yVelocity = (yVelocity/xVelocity)*minVelocity;
				xVelocity = minVelocity;
			}
			if(yVelocity < minVelocity && yVelocity > xVelocity) {
				xVelocity = (xVelocity/yVelocity)*minVelocity;
				yVelocity = minVelocity;
			}
			if(vect.getX() > part.getLocation().getX()) {
				part.getLocation().add(xVelocity, 0f, 0f);
			}
			if(vect.getX() < part.getLocation().getX()) {
				part.getLocation().add(-xVelocity, 0f, 0f);
			}
			if(vect.getY() > part.getLocation().getY()) {
				part.getLocation().add(0f, yVelocity, 0f);
			}
			if(vect.getY() < part.getLocation().getY()) {
				part.getLocation().add(0f, -yVelocity, 0f);
			} 
			if(Math.abs(part.getLocation().getX()-vect.getX()) < 10 && Math.abs(part.getLocation().getY()-vect.getY()) < 10) {
				part.regenerate = false;
				if(!hit && !InGameState.getMap().isPosEmpty(target.getX(), target.getY()))  {
					InGameState.getMap().getPos(target.getX(), target.getY()).damaged(damage);
					hit = true;
				}
				if(part.isDead()) {
					WeaponHandler.getInstance().removeWeapon(this);
				}
			}
		}
		else{
			WeaponHandler.getInstance().removeWeapon(this);
		}
	}
	/**
	 * Returns the node with the weapon.
	 * @return
	 */
	public Entity getNode() {
		return part;
	}
	
	protected abstract Particles getWeapon();

}
