/**
 * Copyright © 2009-2010, Bruce-Robert Pocock & Res Interactive, LLC.
 * All Rights Reserved. Licensed for perpetual use, modification, and/or
 * distribution by either party.
 * 
 * @author brpocock
 */
package com.tootsville.game;

import org.json.JSONObject;
import org.starhope.appius.game.*;
import org.starhope.appius.user.AbstractUser;
import org.starhope.appius.util.AppiusConfig;
import org.starhope.util.LibMisc;

/**
 * @author brpocock, theys, rdawson
 * 
 */
public final class ZapAttack extends LaserTagGame {

	/**
	 * The POJO serialization ID
	 */
	private static final long serialVersionUID = -3405419666711244842L;

	/**
	 * @param z the zone in which the game is being played
	 */
	public ZapAttack (final Zone z) {
		super (z);
		gameState = GameStateFlag.GAME_SOLO;
		gameCode = 'Z';

		for (final String moniker : new String [] { "zapArena1",
				"zapArena2", "zapArena3", "zapArena4" }) {
			final Room r = z.getRoomByName (moniker);
			if (null == r)
				throw AppiusClaudiusCaecus
				.fatalBug ("Can't find room by moniker "
						+ moniker + " in zone " + z.getName ());
			rooms.add (r);
		}

		scoreWatchRooms.add (z.getRoomByName ("zapLobby"));
		for (final AbstractRoom r : rooms) {
			r.add (this);
		}
		AppiusClaudiusCaecus.add (this);
		acceptGameStateChange (this, GameStateFlag.GAME_SOLO);
	}

	/**
	 * 
	 * Accept notification of game state change. Set up practice mode,
	 * if necessary; clear remaining targets upon leaving practice mode.
	 * 
	 * @param game This game, hopefully.
	 * @param newGameState The state into which we are entering.
	 * 
	 */
	@Override
	public void acceptGameStateChange (final GameEvent game,
			final GameStateFlag newGameState) {
		if (newGameState == GameStateFlag.GAME_SOLO
				|| AppiusConfig
				.getConfigBoolOrFalse ("com.tootsville.game.ZapAttack.combatRocks")) {
			// establish targets for target practice
			final int left = AppiusConfig.getIntOrDefault (
					"com.tootsville.game.ZapAttack.left", 100);
			final int right = AppiusConfig.getIntOrDefault (
					"com.tootsville.game.ZapAttack.right", 700);
			final int top = AppiusConfig.getIntOrDefault (
					"com.tootsville.game.ZapAttack.top", 100);
			final int bottom = AppiusConfig.getIntOrDefault (
					"com.tootsville.game.ZapAttack.bottom", 400);
			final int rockRatio = AppiusConfig.getIntOrDefault (
					"com.tootsville.game.ZapAttack.rockRatio", 3);
			final int minTargets = AppiusConfig.getIntOrDefault (
					"com.tootsville.game.ZapAttack.minTargets", 4);
			final int maxTargets = AppiusConfig.getIntOrDefault (
					"com.tootsville.game.ZapAttack.maxTargets", 8);
			for (final Room r : getRooms ()) {
				final int numTargets = AppiusConfig.getRandomInt (
						minTargets, maxTargets);
				for (int i = 0; i < numTargets; ++i) {
					final String varExists = r.getVariable ("t~" + i);
					if (null == varExists || "".equals (varExists)) {
						final int x = AppiusConfig.getRandomInt (left,
								right);
						final int y = AppiusConfig.getRandomInt (top,
								bottom);
						final String type;
						final int subType;
						if (AppiusConfig.getRandomInt (0, rockRatio) == 0) {
							type = "itm";
							subType = AppiusConfig.getRandomInt (0, 2);
						} else {
							type = "obs";
							subType = 0;
						}

						r.setVariable ("t~" + i, type + "~" + subType
								+ "~" + x + "~" + y);
					}
				}
			}
		} else if ( !AppiusConfig
				.getConfigBoolOrFalse ("com.tootsville.game.ZapAttack.combatRocks")) {
			// eliminate any remaining targets on leaving solo mode
			for (final Room r : getRooms ()) {
				for (final String roomVarName : r.getVariables ()
						.keySet ()) {
					if (roomVarName.startsWith ("t~")) {
						r.deleteVariable (roomVarName);
					}
				}
			}
		}
		super.acceptGameStateChange (game, newGameState);
	}

	/**
	 * @see org.starhope.appius.game.RoomListener#acceptObjectJoinRoom(AbstractRoom,
	 *      org.starhope.appius.game.RoomListener)
	 */
	@Override
	public void acceptObjectJoinRoom (final AbstractRoom room,
			final RoomListener object) {
		super.acceptObjectJoinRoom (room, object);
		if (GameStateFlag.GAME_RUNNING == gameState) {
			sendStartEvents ("ZapAttack.game");
		}
	}

	/**
	 * @see org.starhope.appius.game.RoomListener#acceptOutOfBandMessage(AbstractUser, AbstractRoom, JSONObject)
	 */
	public void acceptOutOfBandMessage (final AbstractUser sender,
			final AbstractRoom room, final JSONObject body) {
		noOp ();
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.RoomListener#acceptPublicMessage(AbstractUser, AbstractRoom, String)
	 */
	@Override
	public void acceptPublicMessage (final AbstractUser sender,
			final AbstractRoom room, final String message) {
		noOp ();
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.RoomListener#acceptPublicMessage(org.starhope.appius.user.AbstractUser,
	 *      java.lang.String)
	 */
	public void acceptPublicMessage (final AbstractUser from,
			final String message) {
		noOp ();
	}

	/**
	 * 
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.GameEvent#equals(java.lang.Object)
	 */
	@Override
	public boolean equals (final Object other) {
		if (null == other) return false;
		if (other instanceof ZapAttack)
			return equals ((ZapAttack) other);
		return false;
	}

	/**
	 * Determine if two instance pointers to Zap Attack are, in fact,
	 * the same instance
	 * 
	 * @param other Another ZapAttack instance against which to compare
	 *            this one
	 * @return true, if the two objects refer to the same game instance
	 */
	public boolean equals (final ZapAttack other) {
		if (null == other) return false;
		return getCacheUniqueID ().equals (other.getCacheUniqueID ());
	}

	/**
	 * @see org.starhope.appius.sql.SQLPeerDatum#flush()
	 */
	@Override
	public void flush () {
		AppiusClaudiusCaecus.reportBug ("wtf?");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.LaserTagGame#getGameEventPrefix()
	 */
	@Override
	public String getGameEventPrefix () {
		return "ZapAttack";
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.util.HasName#getName()
	 */
	public String getName () {
		return "ZapAttack in " + rooms.first ().getZone ().getName ();
	}

	/**
	 * @see org.starhope.appius.game.LaserTagGame#getScoreForObject(String,
	 *      int)
	 */
	@Override
	protected int getScoreForObject (final String type,
			final int subtype) {
		return AppiusConfig.getIntOrDefault (
				"com.tootsville.games.ZapAttack." + type + "."
				+ subtype + ".score", (1 + subtype));
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.GameEvent#hashCode()
	 */
	@Override
	public int hashCode () {
		return LibMisc.makeHashCode (getCacheUniqueID ());
	}

	/**
	 * Guess what this doesn't do? Everything!
	 */
	public void noOp () {
		// No op.
	}

}
