package ei.game.input;

import java.util.ArrayList;

import ei.engine.LWJGLGameWindow;
import ei.engine.input.MouseInput;
import ei.engine.math.Vector2f;
import ei.engine.math.Vector2i;
import ei.engine.math.Vector4f;
import ei.engine.scene.Box;
import ei.engine.scene.Sprite;
import ei.engine.texture.Texture;
import ei.game.scene.GameEntity;
import ei.game.scene.Map;

public class InGameMouseInput extends MouseInput{
	private static final int CAMERA_MOVE_BORDER = 40;
	private static final float CAMERA_MOVE_SPEED = 6.0f;

	private ArrayList<GameEntity> selected;
	private GameEntity oldMouseOver;
	private Vector2f leftKlickPos;
	private Box markingBox;

	private Map map;

	public InGameMouseInput(Map map) {
		super("InGameMouseInput","data/cursor/cursor.png");
		this.map = map;
		this.selected = new ArrayList<GameEntity>();

		//inits the mouse texture
		Sprite s = getSprite();		
		s.setSize(new Vector2f(38,50));

		Texture tex = new Texture();
		tex.setColor(new Vector4f(0.5f, 1.0f, 0.5f,1));
		markingBox = new Box("MarkingBob", tex);
	}

	@Override
	public void mouseUpdate(int x, int y, int w) {
		removeDead();
		
		// mov cam to the left
		if(x < CAMERA_MOVE_BORDER){
			LWJGLGameWindow.getCamera().getLocation().add(-CAMERA_MOVE_SPEED,0,0);
		}
		// mov cam to the right
		if(x > LWJGLGameWindow.getWidth()-CAMERA_MOVE_BORDER){
			LWJGLGameWindow.getCamera().getLocation().add(CAMERA_MOVE_SPEED,0,0);
		}
		// mov cam upp
		if(y < CAMERA_MOVE_BORDER){
			LWJGLGameWindow.getCamera().getLocation().add(0,-CAMERA_MOVE_SPEED,0);
		}
		// mov cam down
		if(y > LWJGLGameWindow.getHeight()-CAMERA_MOVE_BORDER){
			LWJGLGameWindow.getCamera().getLocation().add(0,CAMERA_MOVE_SPEED,0);
		}

		Vector2i pos = Map.getPosByPixel(
				LWJGLGameWindow.getCamera().getLocation().getX()+x,
				LWJGLGameWindow.getCamera().getLocation().getY()+y);

		if(map.posExist(pos.getX(), pos.getY())){
			// The marking box is sized and positioned
			if(leftKlickPos != null){
				float markingSizeX = 0;
				float markingSizeY = 0;

				if(leftKlickPos.getX() > (LWJGLGameWindow.getCamera().getLocation().getX()+x)){
					markingSizeX = Math.abs(leftKlickPos.getX()-(LWJGLGameWindow.getCamera().getLocation().getX()+x));
				}
				else{
					markingSizeX = -Math.abs(leftKlickPos.getX()-(LWJGLGameWindow.getCamera().getLocation().getX()+x));
				}

				if(leftKlickPos.getY() > (LWJGLGameWindow.getCamera().getLocation().getY()+y)){
					markingSizeY = Math.abs(leftKlickPos.getY()-(LWJGLGameWindow.getCamera().getLocation().getY()+y));			
				}
				else{
					markingSizeY = -Math.abs(leftKlickPos.getY()-(LWJGLGameWindow.getCamera().getLocation().getY()+y));			
				}

				markingBox.setSize(new Vector2f(markingSizeX+getSprite().getSize().getX()/2,markingSizeY+getSprite().getSize().getY()/2));
				markingBox.setLocation(new Vector2f(
						leftKlickPos.getX()-markingBox.getSize().getX()/2,
						leftKlickPos.getY()-markingBox.getSize().getY()/2));
			}

			// Make unit mouseover select
			if(!map.isPosEmpty(pos.getX(), pos.getY())){
				if(oldMouseOver != map.getPos(pos.getX(), pos.getY())){
					if(oldMouseOver != null)oldMouseOver.setMouseOver(false);
					oldMouseOver = map.getPos(pos.getX(), pos.getY());
					oldMouseOver.setMouseOver(true);
				}
			}
			else{
				if(oldMouseOver != null)oldMouseOver.setMouseOver(false);
			}
		}
	}

	@Override
	public void mouseDown(int event,int x, int y) {
		Vector2i pos = Map.getPosByPixel(
				LWJGLGameWindow.getCamera().getLocation().getX()+x,
				LWJGLGameWindow.getCamera().getLocation().getY()+y);
		removeDead();
		if(map.posExist(pos.getX(), pos.getY())){
			//selecting unit.
			if(event==LEFT_MOUSE_BUTTON){
				//map.printAllUnits();
				if(leftKlickPos == null){
					leftKlickPos = new Vector2f(
							LWJGLGameWindow.getCamera().getLocation().getX()+x,
							LWJGLGameWindow.getCamera().getLocation().getY()+y);
					markingBox.setSize(new Vector2f(0,0));
					getNode().add(markingBox);
				}
			}
			//unit action.
			else if(event==RIGHT_MOUSE_BUTTON) {
				if(!map.isPosEmpty(pos.getX(), pos.getY())){
					for(int i=0; i<selected.size(); i++) {
						selected.get(i).attack(new Vector2i(pos.getX(), pos.getY()));
					}
				}
				else{
					//MultiPrintStream.out.println("Moving: "+pos.getX()+", "+pos.getY());
					for(int i=0; i<selected.size() ;i++){
						selected.get(i).move(pos.getX(),pos.getY());
					}
				}
			}
		}
	}

	@Override
	public void mouseUp(int event,int x, int y) {
		Vector2i pos = Map.getPosByPixel(
				LWJGLGameWindow.getCamera().getLocation().getX()+x,
				LWJGLGameWindow.getCamera().getLocation().getY()+y);
		removeDead();
		if(map.posExist(pos.getX(), pos.getY())){
			if(leftKlickPos != null){
				deselectAllUnits();
				selectUnits(Map.getPosByPixel(leftKlickPos.getX(), leftKlickPos.getY()),pos);
				leftKlickPos = null;
				getNode().remove(markingBox);
			}
		}
	}

	public void removeDead(){
		for(int i=0; i<selected.size() ;i++){
			if(selected.get(i).getLife() <= 0){
				selected.remove(i);
			}
		}
	}
	
	/**
	 * Selecting all the units between the two positions
	 * 
	 * @param startPos The start position
	 * @param stopPos The stop position
	 */
	public void selectUnits(Vector2i startPos, Vector2i stopPos){
		for(int i=Math.min(startPos.getX(), stopPos.getX()); i<=Math.max(startPos.getX(), stopPos.getX()) ;i++){
			for(int j=Math.min(startPos.getY(), stopPos.getY()); j<=Math.max(startPos.getY(), stopPos.getY()) ;j++){
				if(!map.isPosEmpty(i, j)){
					selected.add(map.getPos(i, j));
					map.getPos(i, j).setSelected(true);	
				}
			}
		}
	}

	/**
	 * Deselects all the units
	 *
	 */
	public void deselectAllUnits(){
		for(int i=0; i<selected.size(); i++) {
			selected.get(i).setSelected(false);
		}
		selected.clear();
	}

}
