package ei.game.scene.buildings;

import java.util.LinkedList;

import ei.engine.math.Vector2f;
import ei.engine.math.Vector2i;
import ei.engine.scene.Entity;
import ei.engine.scene.Node;
import ei.game.gamestate.InGameState;
import ei.game.player.Player;
import ei.game.scene.GameEntity;
import ei.game.scene.Map;
import ei.game.scene.SelectBox;
import ei.game.scene.units.Unit;

/**
 * The Building class, handles buildings, this case CommandCenter class.
 * @author Jesper Lundin
 *
 */
public abstract class Building extends GameEntity{
	private LinkedList<Unit> buildQueue;
	private int buildTime;
	private Node unitNode;
	private Vector2i oldPos;
	private Vector2f moveFrom;
	private Vector2f moveTo;
	private int size;


	public Building(int l, Vector2i pos, Player p, int size) {
		super(l, p);
		this.size = size;
		buildQueue = new LinkedList<Unit>();
		unitNode = new Node("BuildingNode");
		unitNode.setLocation(Map.getPixelByPos(pos.getX(), pos.getY(), this.size));
		setPos(pos.getX(), pos.getY(), this.size);
		moveFrom = Map.getPixelByPos(oldPos.getX()+size-2, oldPos.getY()+size-2);
		moveTo = Map.getPixelByPos( oldPos.getX()+size-2, oldPos.getY()+size);
		
		moveFrom.sub(unitNode.getLocation().getX()-20,unitNode.getLocation().getY());
		moveTo.sub(unitNode.getLocation().getX(),unitNode.getLocation().getY());
		
		initGraphics();
	}
	
	public void setSelected(Player p,boolean b, boolean playSound) {
		if(getSelection() != null){
			if(b) {
				SelectBox box = getSelection();
				if(getPlayer() != p){
					box.setColor(SelectBox.COLOR_RED);
					unitNode.add(box.getSelectNode());
				}
				else{
					box.setColor(SelectBox.COLOR_GREEN);
					unitNode.add(box.getSelectNode());	
				}
			}
			else{
				unitNode.remove(getSelection().getSelectNode());
			}
		}
	}
	
	public void setMouseOver(Player p,boolean b) {
		if(getSelection() != null){
			if(b) {
				SelectBox box = getSelection();
				if(getPlayer() != p){
					box.setColor(SelectBox.COLOR_RED);
					unitNode.add(box.getMouseOverNode());
				}
				else{
					box.setColor(SelectBox.COLOR_GREEN);
					unitNode.add(box.getMouseOverNode());	
				}
			}
			else{
				unitNode.remove(getSelection().getMouseOverNode());
			}
		}
	}
	/**
	 * Sets the size of the building.
	 * @param size
	 */
	public void setSize(int size) {
		this.size = size;
	}
	/**
	 * Returns the sprite for the unit
	 * 
	 * @return The sprite for the unit
	 */
	public Node getNode(){
		return unitNode;
	}
	public boolean isTerrain() {
		return false;
	}
	
	/**
	 * Changes the pos of the unit in the map
	 * 
	 * @param x The x pos to move to
	 * @param y The y pos to move to
	 */
	public void setPos(int x, int y, int size) {
		if(oldPos!=null) {
			InGameState.getMap().removeBuildPos(oldPos.getX(), oldPos.getY(), size);
		}
		oldPos = new Vector2i(x, y);
		InGameState.getMap().setBuildPos(this, x, y, size);
	}

	/**
	 * Adds a unit to the build queue
	 * @param u The unit to build
	 */
	public void buildUnit(Unit u){
		buildQueue.addLast(u);
	}
	
	/**
	 * Returns the size of the build queue
	 * @return The size of the build queue
	 */
	public int getBuildQueueSize(){
		return buildQueue.size();
	}
	
	/**
	 * Removes the last unit in the build queue
	 *
	 */
	public void removeLast(){
		if(!buildQueue.isEmpty()){
			buildQueue.removeLast();
		}
	}
	
	/**
	 * Returns the procentage of completion of the unit
	 *
	 */
	public int getBuildProgress(){
		if(buildQueue.isEmpty()){
			return 0;
		}
		int progress = (int)(((float)buildTime/buildQueue.peek().getBuildTime())*100);
		if(progress > 100){
			progress = 100;
		}				
		return progress;
	}
	
	/**
	 * Removes this building from the game.
	 *
	 */	
	public void remove(){
		unitNode.remove(getSprite());
		getPlayer().removeUnit(this);
		InGameState.getMap().removeBuildPos(oldPos.getX(), oldPos.getY(), this.size);
	}
	
	/**
	 * Updating the unit
	 */
	public void update() {		
		if(getLife() <= 0) {
			destroyed();
			remove();
		}
		
		if(!buildQueue.isEmpty() && getPlayer().getKredits() >= buildQueue.peek().getPrice()){
			if(buildTime == 0){
				getPlayer().addKredits(-buildQueue.peek().getPrice());
			}
			buildTime++;
			if(buildTime >= buildQueue.peek().getBuildTime()){
				if(!unitNode.contains(buildQueue.peek().getNode())){
					unitNode.add(buildQueue.peek().getNode(),unitNode.size()/2);
					buildQueue.peek().getNode().setLocation(moveFrom);
				}
				Vector2i temp = Map.getPosByPixel(moveTo.getX()+unitNode.getLocation().getX(), moveTo.getY()+unitNode.getLocation().getY());

				if(!InGameState.getMap().isPosEmpty(temp.getX(),temp.getY())){
					InGameState.getMap().getPos(temp.getX(),temp.getY()).move(false, oldPos.getX()+(size/2), oldPos.getY()-(size/2));
				}
				else{
					//The moving is done here.
					if(moveTo.getX() > buildQueue.peek().getNode().getLocation().getX()) {
						buildQueue.peek().getNode().getLocation().add(buildQueue.peek().getVelocity(), 0f, 0f);
					}
					if(moveTo.getX() < buildQueue.peek().getNode().getLocation().getX()) {
						buildQueue.peek().getNode().getLocation().add(-buildQueue.peek().getVelocity(), 0f, 0f);
					}
					if(moveTo.getY() > buildQueue.peek().getNode().getLocation().getY()) {
						buildQueue.peek().getNode().getLocation().add(0f, buildQueue.peek().getVelocity(), 0f);
					}
					if(moveTo.getY() < buildQueue.peek().getNode().getLocation().getY()) {
						buildQueue.peek().getNode().getLocation().add(0f, -buildQueue.peek().getVelocity(), 0f);
					}
					
					if(Math.abs(moveTo.getX() - buildQueue.peek().getNode().getLocation().getX()) < buildQueue.peek().getVelocity()+1
							&& Math.abs(moveTo.getY() - buildQueue.peek().getNode().getLocation().getY())< buildQueue.peek().getVelocity()+1 ){
						buildTime = 0;
						unitNode.remove(buildQueue.peek().getNode());
						buildQueue.peek().forcePos(temp.getX(),temp.getY());
						getPlayer().addUnit(buildQueue.poll());
					}
				}
			}
		}
	}
	
	public abstract Entity getGroundSprite();
	
	public Vector2i getPos() {
		return oldPos;
	}
	public boolean isAttacking() {
		return false;
	}
	public boolean isMoving(){
		return false;
	}
}

