
import java.awt.Rectangle;

public abstract class Entity {
	/** The current x location of this entity */ 
	protected double x;
	/** The current y location of this entity */
	protected double y;
	/** The sprite that represents this entity */
	public Sprite sprite;
	/** The current speed of this entity horizontally (pixels/sec) */
	protected double dx;
	/** The current speed of this entity vertically (pixels/sec) */
	protected double dy;
	/** The rectangle used for this entity during collisions  resolution */
	public Rectangle me = new Rectangle();
	/** The rectangle used for other entities during collision resolution */
	public Rectangle him = new Rectangle();
	
	public boolean customSize = false;
	public Rectangle rect = new Rectangle();
	
	boolean solid = false;
	
	/**
	 * Construct a entity based on a sprite image and a location.
	 * 
	 * @param ref The reference to the image to be displayed for this entity
 	 * @param x The initial x location of this entity
	 * @param y The initial y location of this entity
	 */
	public Entity(String ref, int x, int y, int rx, int ry, int rw, int rh, boolean solid) {
		this.solid = solid;
		this.sprite = ResourceFactory.get().getSprite(ref);
		this.x = x;
		this.y = y;
		
		if (rx != -1) { // Custom collision border
			setBounds(x + rx, y + ry, rw, rh);
		}
	}
	
	public void setBounds(int rx, int ry, int rw, int rh) {
		customSize = true;
		rect.setBounds(rx, ry, rw, rh);
	}
	
	/**
	 * Request that this entity move itself based on a certain ammount
	 * of time passing.
	 * 
	 * @param delta The ammount of time that has passed in milliseconds
	 */
	public void move(long delta) {
		// update the location of the entity based on move speeds
		x += (delta * dx) / 1000;
		y += (delta * dy) / 1000;
	}
	
	public boolean isCustomSize() {
		return customSize;
	}
	
	public boolean isStill() {
		return (dx > -1 && dx < 1); //  && dy > -1 && dy < 1 TODO
	}
	
	/**
	 * Set the horizontal speed of this entity
	 * 
	 * @param dx The horizontal speed of this entity (pixels/sec)
	 */
	public void setHorizontalMovement(double dx) {
		this.dx = dx;
	}

	/**
	 * Set the vertical speed of this entity
	 * 
	 * @param dy The vertical speed of this entity (pixels/sec)
	 */
	public void setVerticalMovement(double dy) {
		this.dy = dy;
	}
	
	/**
	 * Get the horizontal speed of this entity
	 * 
	 * @return The horizontal speed of this entity (pixels/sec)
	 */
	public double getHorizontalMovement() {
		return dx;
	}

	/**
	 * Get the vertical speed of this entity
	 * 
	 * @return The vertical speed of this entity (pixels/sec)
	 */
	public double getVerticalMovement() {
		return dy;
	}
	
	/**
	 * Draw this entity to the graphics context provided
	 */
	public void draw() {
		sprite.draw((int) x,(int) y);
	}
	
	/**
	 * Do the logic associated with this entity. This method
	 * will be called periodically based on game events
	 */
	public void doLogic() {
	}
	
	/**
	 * Get the x location of this entity
	 * 
	 * @return The x location of this entity
	 */
	public int getX() {
		return (int) x;
	}

	/**
	 * Get the y location of this entity
	 * 
	 * @return The y location of this entity
	 */
	public int getY() {
		return (int) y;
	}
	
	public void setPos(double x, double y) {
		this.x = x;
		this.y = y;
	}
	
	/**
	 * Check if this entity collised with another.
	 * 
	 * @param other The other entity to check collision against
	 * @return True if the entities collide with each other
	 */
	public boolean collidesWith(Entity other) {
		if (!customSize) {
			me.setBounds((int) x,(int) y, sprite.getWidth(), sprite.getHeight());
		} else {
			me.setBounds((int) rect.x, (int) rect.y, (int) rect.getWidth(), (int) rect.getHeight());
		}
		if (!other.customSize) {
			him.setBounds((int) other.x, (int) other.y, other.sprite.getWidth(), other.sprite.getHeight());
		} else {
			him.setBounds((int) other.rect.x, (int) other.rect.y, (int) other.rect.getWidth(), (int) other.rect.getHeight());
		}
		return me.intersects(him);
	}
	
	/**
	 * Notification that this entity collided with another.
	 * 
	 * @param other The entity with which this entity collided.
	 */
	public abstract void collidedWith(Entity other);
}