package com.fundynamic.d2tm.game.controls;

import com.fundynamic.d2tm.game.behaviors.Moveable;
import com.fundynamic.d2tm.game.behaviors.Selectable;
import com.fundynamic.d2tm.game.entities.Entity;
import com.fundynamic.d2tm.game.entities.Player;
import com.fundynamic.d2tm.game.map.Cell;
import com.fundynamic.d2tm.math.Vector2D;

/**
 * This class represents the state of the mouse. This is not about coordinates (we can get these via Slick listeners)
 * but about what structure is selected, the type of mouse being rendered (ie moving? attacking? placing structure? or
 * 'normal' ?)
 */
public class Mouse {

    private Player playerControlled;

    private Cell hoverCell;
    private Entity lastSelectedEntity;
    private boolean movingCursor;

    public Mouse(Player playerControlled) {
        this.playerControlled = playerControlled;
    }

    public Mouse(Cell hoverCell) {
        this.playerControlled = null;
        this.hoverCell = hoverCell;
    }

    public void setHoverCell(Cell cell) {
        if (cell == null) throw new IllegalArgumentException("argument cell may not be null");
        this.hoverCell = cell;
    }

    public Cell getHoverCell() {
        return hoverCell;
    }

    public Vector2D getHoverCellMapVector() {
        return hoverCell.getCoordinatesAsVector2D();
    }

    /**
     * When a structure is bound to a cell, this method makes sure that is the only selected structure.
     * If there is no structure bound to the cell then this automatically deselects the structure.
     */
    public void selectEntity() {
        if (hoverCell == null) return;
        Entity entity = hoverCell.getEntity();
        if (entity == null) return;
        if (!entity.isSelectable()) return;
        lastSelectedEntity = entity;
        ((Selectable)lastSelectedEntity).select();
        if (selectedEntityBelongsToPlayerControlled() && selectedEntityIsMovable()) {
            movingCursor = true;
        }
    }

    public boolean hasAnyEntitySelected() {
        return this.lastSelectedEntity != null;
    }

    public Entity getLastSelectedEntity() {
        return lastSelectedEntity;
    }

    public void deselectEntity() {
        if (lastSelectedEntity != null) {
            if (lastSelectedEntity.isSelectable()) {
                ((Selectable) lastSelectedEntity).deselect();
            }
        }
        if (selectedEntityBelongsToPlayerControlled()) {
            movingCursor = false;
        }
        lastSelectedEntity = null;
    }

    private boolean selectedEntityBelongsToPlayerControlled() {
        if (lastSelectedEntity == null) return false;
        if (playerControlled == null) return false;
        return lastSelectedEntity.getPlayer().equals(playerControlled);
    }

    public boolean hoversOverSelectableEntity() {
        Entity entity = hoverCell.getEntity();
        if (entity == null) return false;
        return entity.isSelectable();

    }

    public boolean isMovingCursor() {
        return movingCursor;
    }

    public void moveSelectedEntityToHoverCell() {
        if (selectedEntityBelongsToPlayerControlled() && selectedEntityIsMovable()) {
            ((Moveable)lastSelectedEntity).moveTo(getHoverCellMapVector());
        }
    }

    private boolean selectedEntityIsMovable() {
        return lastSelectedEntity.isMovable();
    }
}

@@ -627,32 +627,33 @@
  Player 
-playerControlled
+controllingPlayer
 ;%0A%0A    p
@@ -773,32 +773,33 @@
 (Player 
-playerControlled
+controllingPlayer
 ) %7B%0A    
@@ -811,43 +811,45 @@
 his.
-playerC
+c
 ontroll
-ed = p
+ingP
 layer
-C
+ = c
 ontroll
-ed
+ingPlayer
 ;%0A  
@@ -901,32 +901,33 @@
    this.
-playerControlled
+controllingPlayer
  = null;
@@ -1854,38 +1854,32 @@
 ityBelongsTo
-Player
 Controll
 ed() && sele
@@ -1858,34 +1858,41 @@
 elongsToControll
-ed
+ingPlayer
 () && selectedEn
@@ -2392,38 +2392,32 @@
 ityBelongsTo
-Player
 Controll
 ed()) %7B%0A    
@@ -2404,18 +2404,25 @@
 Controll
-ed
+ingPlayer
 ()) %7B%0A  
@@ -2544,38 +2544,32 @@
 ityBelongsTo
-Player
 Controll
 ed() %7B%0A     
@@ -2556,18 +2556,25 @@
 Controll
-ed
+ingPlayer
 () %7B%0A   
@@ -2636,32 +2636,33 @@
     if (
-playerControlled
+controllingPlayer
  == null
@@ -2734,24 +2734,25 @@
 als(
-playerControlled
+controllingPlayer
 );%0A 
@@ -3105,22 +3105,16 @@
 gsTo
-Player
 Controll
 ed()
@@ -3109,18 +3109,25 @@
 Controll
-ed
+ingPlayer
 () && se

rename to controllingPlayer because that sounds less booleanish