/**
 * Copyright © 2010, Res Interactive, LLC
 */
package com.tootsville.npc;

import java.util.concurrent.atomic.AtomicInteger;

import org.json.JSONObject;
import org.starhope.appius.except.GameLogicException;
import org.starhope.appius.except.NotFoundException;
import org.starhope.appius.except.PrivilegeRequiredException;
import org.starhope.appius.except.UserDeadException;
import org.starhope.appius.game.DamageArea;
import org.starhope.appius.game.DamageTypeRanks;
import org.starhope.appius.geometry.Sphere;
import org.starhope.appius.geometry.Coord2D;
import org.starhope.appius.geometry.Coord3D;
import org.starhope.appius.geometry.PolygonPrimitive;
import org.starhope.appius.geometry.Vector2D;
import org.starhope.appius.physica.Geometry;
import org.starhope.appius.room.Room;
import org.starhope.appius.room.RoomListener;
import org.starhope.appius.user.AbstractNonPlayerCharacter;
import org.starhope.appius.user.AbstractUser;
import org.starhope.appius.user.Nomenclator;

/**
 * WRITEME
 * 
 * @author ewinkelman
 */
public class SoccerBall extends AbstractNonPlayerCharacter {

	/**
	 * WRITEME: Document this brpocock@star-hope.org
	 */
	private static final long serialVersionUID = 8593896744538972677L;

	/**
	 * Static next instance ID for keeping track of instances of soccer
	 * balls
	 */
	private static AtomicInteger nextInstanceID = new AtomicInteger ();

	/**
	 * ball radius
	 */
	protected final int BALL_RADIUS = 10;

	/**
	 * Create an instance of a soccer ball
	 * 
	 * @throws GameLogicException WRITEME
	 * @throws NotFoundException WRITEME
	 */
	public SoccerBall () throws NotFoundException, GameLogicException {
		super ("$SoccerBall");
		setVariable ("noClick", "true");
		final DamageTypeRanks defense = new DamageTypeRanks ();
		defense.add (Nomenclator.getDataRecord (DamageArea.class,
				"Shadow"), 100);
		changeBaseDefenses (defense);
	}

	/**
	 * pass-through visibility of super constructor for volleyball
	 * 
	 * @param who WRITEME
	 * @throws NotFoundException WRITEME
	 * @throws GameLogicException WRITEME
	 */
	protected SoccerBall (final String who) throws NotFoundException,
			GameLogicException {
		super (who);
	}

	/**
	 * @see org.starhope.appius.room.RoomListener#acceptObjectJoinRoom(org.starhope.appius.room.Room,
	 *      org.starhope.appius.room.RoomListener)
	 */
	@Override
	public void acceptObjectJoinRoom (final Room room,
			final RoomListener object) {
		// TODO brpocock@star-hope.org Auto-generated method stub (Jul
		// 30,
		// 2010)

	}

	/**
	 * @see org.starhope.appius.room.RoomListener#acceptObjectPartRoom(org.starhope.appius.room.Room,
	 *      org.starhope.appius.room.RoomListener)
	 */
	@Override
	public void acceptObjectPartRoom (final Room room,
			final RoomListener thing) {
		// TODO brpocock@star-hope.org Auto-generated method stub (Jul
		// 30,
		// 2010)

	}

	/**
	 * @see org.starhope.appius.room.RoomListener#acceptOutOfBandMessage(org.starhope.appius.user.AbstractUser,
	 *      org.starhope.appius.room.Room, org.json.JSONObject)
	 */
	@Override
	public void acceptOutOfBandMessage (final AbstractUser sender,
			final Room room, final JSONObject body) {
		// TODO brpocock@star-hope.org Auto-generated method stub (Jul
		// 30,
		// 2010)

	}

	/**
	 * @see org.starhope.appius.room.RoomListener#acceptUserVariableUpdate(org.starhope.appius.user.AbstractUser,
	 *      java.lang.String, java.lang.String)
	 */
	@Override
	public void acceptUserVariableUpdate (final AbstractUser user,
			final String varName, final String varValue) {
		// TODO brpocock@star-hope.org Auto-generated method stub (Jul
		// 30,
		// 2010)

	}

	/**
	 * @see org.starhope.appius.user.AbstractUser#ban(org.starhope.appius.user.AbstractUser,
	 *      java.lang.String)
	 */
	@Override
	public void ban (final AbstractUser u, final String banReason)
			throws PrivilegeRequiredException {
		// TODO brpocock@star-hope.org Auto-generated method stub (Jul
		// 30,
		// 2010)

	}

	/**
	 * @see org.starhope.appius.physica.Collidable#getCenterOfMass()
	 */
	@Override
	public Coord2D getCenterOfMass () {
		return getLocation ().toCoord2D ();
	}

	/**
	 * @see org.starhope.appius.physica.Collidable#getCollisionBounds()
	 */
	@Override
	public PolygonPrimitive <?> getCollisionBounds () {
		return new Sphere (getLocation ().toCoord2D (), BALL_RADIUS);
	}

	/**
	 * Ball is velocity based and doesn't have predetermined start/stop
	 * 
	 * @see org.starhope.appius.physica.Collidable#getEndMovementTime(long)
	 */
	@Override
	public long getEndMovementTime (final long currentTime) {
		return Geometry.getTimeToTarget (this, currentTime)
				+ currentTime;
	}

	/**
	 * @see org.starhope.appius.user.AbstractNonPlayerCharacter#getInstanceID()
	 */
	@Override
	protected int getInstanceID () {
		return SoccerBall.nextInstanceID.incrementAndGet ();
	}

	/**
	 * @see org.starhope.appius.physica.Collidable#getMass()
	 */
	@Override
	public double getMass () {
		return 2.0d;
	}

	/**
	 * @see org.starhope.appius.physica.Collidable#getStartMovementTime()
	 */
	@Override
	public long getStartMovementTime () {
		return getStartT ();
	}

	/**
	 * @return WRITEME
	 * @see org.starhope.appius.physica.Collidable#getVelocity()
	 */
	@Override
	public synchronized Vector2D getVelocity () {
		final Coord3D loc = getLocation ();
		final Coord3D target = getTarget ();
		Vector2D result = new Vector2D (target.getX () - loc.getX (),
				target.getY () - loc.getY ());
		if (result.length () != 0) {
			result = result.normalize ();
		}
		result = result.scale (getTravelRate ());
		return result;
	}

	/**
	 * @see org.starhope.appius.user.AbstractUser#sendEarnings(org.starhope.appius.room.Room,
	 *      java.lang.String)
	 */
	@Override
	public void sendEarnings (final Room room, final String string) {
		// TODO brpocock@star-hope.org Auto-generated method stub (Jul
		// 30,
		// 2010)

	}

	/**
	 * @see org.starhope.appius.user.AbstractUser#sendWardrobe()
	 */
	@Override
	public void sendWardrobe () {
		// no op
	}

	/**
	 * @param com WRITEME
	 * @see org.starhope.appius.physica.Collidable#setCenterOfMass(Coord2D)
	 */
	@Override
	public void setCenterOfMass (final Coord2D com) {
		final Room aRoom = getRoom ();
		if (null != aRoom) {
			aRoom.putHere (this, com.toCoord3D ());
		}
	}

	/**
	 * @see org.starhope.appius.user.GeneralUser#setTravelRate(double)
	 */
	@Override
	public void setTravelRate (final double rate) {
		userRecord.setTravelRatePrivately (rate);
	}

	/**
	 * @param velocity WRITEME
	 * @see org.starhope.appius.physica.Collidable#setVelocity(Vector2D)
	 */
	@Override
	public synchronized void setVelocity (final Vector2D velocity) {
		final Room aRoom = getRoom ();
		if (null != aRoom) {
			setTravelRate (velocity.length ());
			final Coord3D loc = getLocationForUpdate ();
			try {
				aRoom.goTo (this, loc.add (velocity.getX (), velocity
						.getY (), 0d), null, "Walk");
			} finally {
				unlockLocation ();
			}
		}
	}

	/**
	 * @see org.starhope.appius.util.AcceptsMetronomeTicks#tick(long,
	 *      long)
	 */
	@Override
	public void tick (final long currentTime, final long deltaTime)
			throws UserDeadException {
		// TODO Auto-generated method stub

	}

}
