package de.rico.adventure.entity.hotspot;

import javax.media.opengl.GL;

import de.rico.adventure.entity.AbstractEntity;
import de.rico.engine.camera.culling.ViewingFrustum;
import de.rico.engine.geometry.AbstractMesh;
import de.rico.engine.geometry.Point3D;

/**
 * This abstract class represents an interactive hotspot in the game.
 * Interactives hotspot are invisible volumes that can behave
 * interactively. You can specify, if items can be applied to the
 * hotspot or if the hotspot can be used without an item
 * (such as light switches).
 * @author Frank Bruns
 */
public abstract class AbstractInteractiveHotspot extends AbstractEntity
{
	private Point3D position = null;
	private boolean enabled = true;
	private boolean needsItem = false;

	/**
	 * Creates a new interactive hotspot at the specified position.
	 * You can specify, if items can be applied to the
	 * hotspot or if the hotspot can be used without an item
 	 * (such as light switches).
	 * @param pos position of the hotspot
	 * @param needsItem needs item to use? --> true=yes, false=no
	 */
	public AbstractInteractiveHotspot(Point3D pos, boolean needsItem)
	{
		super(null); // interactive hotspots don't have meshes
		this.position = pos;
		this.needsItem = needsItem;
	}

	/**
	 * Returns the position of the interactive hotspot.
	 * @return position of the interactive hotspot
	 */
	public Point3D getPosition()
	{
		return this.position;
	}

	/**
	 * Sets the position of the interactive hotspot.
	 * @param pos position of the hotspot
	 */
	public void setPosition(Point3D pos)
	{
		this.position = pos;
	}

	/**
	 * Set whether or not the hotspot needs an item applied to
	 * be useable.
	 * @param needsItem needs an item? --> true=yes, false=no
	 */
	public void setNeedsItem(boolean needsItem)
	{
		this.needsItem = needsItem;
	}

	/**
	 * Determines whether or not the hotspot needs an item to
	 * be useable.
	 * @return needs item? --> true=yes, false=no
	 */
	public boolean needsItem()
	{
		return this.needsItem;
	}

	/**
	 * Determines whether or not the interactive hotspot is enabled.
	 * @return is enabled? --> true=yes, false=no
	 */
	@Override
	public boolean isEnabled()
	{
		return this.enabled;
	}

	/**
	 * Sets whether or not this hotspot is enabled.
	 * @param enable set enabled? --> true=yes, false=no
	 */
	@Override
	public void setEnabled(boolean enable)
	{
		this.enabled = enable;
	}



	/**
	 * This method does have no effect on interactive hotspots
	 */
	@Override
	public void destroy()
	{
		// do nothing
	}

	/**
	 * Interactive hotspots don't have meshes assignes, so this method
	 * always returns <code>null</code>.
	 */
	@Override
	public AbstractMesh getMesh()
	{
		return null;
	}

	/* (non-Javadoc)
	 * @see java.lang.Object#toString()
	 */
	@Override
	public String toString()
	{
		return "Hotspot: "+this.getScreenName()+"["+this.position.x+","+this.position.y+","+this.position.z+"]";
	}

	/**
	 * Determines whether the mouse is located over the
	 * interactive hotspot.
	 * @param screenX screen x-coordinate
	 * @param screenY screen y-coordinate
	 * @return is mouse on hotspot? --> true=yes, false=no
	 */
	public abstract boolean isMouseOverHotspot(int screenX, int screenY);


	/**
	 * Returns the world coordinates of the mouse position over the
	 * hotspot.
	 * @param screenX screen x-coordinate
	 * @param screenY screen y-coordinate
	 * @return world position of the mouse over the hotspot
	 */
	public abstract Point3D getMouseOverHotspot(int screenX, int screenY);

	/**
	 * Determines whether or not the hotspot volume is within the
	 * camera's viewing frustum.
	 * @param frustum the camera's viewing frustum
	 * @return is in frustum? --> true=yes, false=no
	 */
	public abstract boolean isWithinFrustum(ViewingFrustum frustum);

	/**
	 * Visualizes the interactive hotspot.
	 * @param gl
	 */
	public abstract void draw(GL gl);
}
