/**
 * <p>
 * Copyright © 2009-2010, Bruce-Robert Pocock
 * </p>
 * <p>
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or (at
 * your option) any later version.
 * </p>
 * <p>
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * General Public License for more details.
 * </p>
 * <p>
 * You should have received a copy of the GNU General Public License
 * along with this program. If not, see <http://www.gnu.org/licenses/>.
 * </p>
 * 
 * @author brpocock
 */
package org.starhope.appius.game;

import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.Map.Entry;

import org.json.JSONException;
import org.json.JSONObject;
import org.starhope.appius.types.AbstractZone;
import org.starhope.appius.user.AbstractUser;

/**
 * WRITEME: The documentation for this type (AbstractRoom) is
 * incomplete. (brpocock, Jan 11, 2010)
 * 
 * @author brpocock
 */
public interface AbstractRoom {

	/**
	 * @param game WRITEME
	 */
	public abstract void add (final GameEvent game);

	/**
	 * TODO: document this method (brpocock, Oct 28, 2009)
	 * 
	 * @param user who
	 * @return true if they are in this room
	 */
	public abstract boolean contains (final AbstractUser user);

	/**
	 * @param string WRITEME
	 */
	public abstract void deleteVariable (final String string);

	/**
	 * WRITEME
	 */
	public abstract void destroySelf ();

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.sql.SQLPeerDatum#flush()
	 */
	public abstract void flush ();

	/**
	 * TODO: document this method (brpocock, Oct 21, 2009)
	 * 
	 * @param jso Serialized form
	 * @throws JSONException if the incoming data isn't in the right
	 *             form
	 */
	public abstract void fromJSON (final JSONObject jso)
	throws JSONException;

	/**
	 * @return WRITEME
	 */
	public abstract Set <RoomListener> getAllListeners ();

	/**
	 * @return WRITEME
	 */
	public abstract Collection <AbstractUser> getAllUsers ();

	/**
	 * <p>
	 * Get the debugging version of the room's name. This is based upon
	 * the moniker and zone, or identifies the room as an abstract room
	 * if it is not a part of a zone.
	 * </p>
	 * 
	 * @return A string uniquely identifying this room for debugging
	 *         purposes.
	 */
	public abstract String getDebugName ();

	/**
	 * @return the filename
	 */
	public abstract String getFilename ();

	/**
	 * @return The Game Event in this room, or (usually) null
	 */
	public abstract GameEvent getGameEvent ();

	/**
	 * Smart Fox Server misspelling of {@link #getID()}
	 * 
	 * @return the room's ID number
	 */
	@Deprecated
	public abstract int getId ();

	/**
	 * @return the room's ID number
	 */
	public abstract int getID ();

	/**
	 * TODO: document this method (brpocock, Nov 24, 2009)
	 * 
	 * @return all RoomListeners, including all users and observers
	 */
	public abstract Collection <RoomListener> getListeners ();

	/**
	 * @return WRITEME
	 */
	public abstract int getMaxUsers ();

	/**
	 * @return the moniker
	 */
	public abstract String getMoniker ();

	/**
	 * TODO: document this method (brpocock, Oct 13, 2009)
	 * 
	 * @return WRITEME
	 */
	public abstract String getMusic ();

	/**
	 * @return WRITEME
	 */
	public abstract String getName ();

	/**
	 * @return the overlay
	 */
	public abstract String getOverlay ();

	/**
	 * @return the owner of this room, if this is a private
	 *         (user-created) room; else, null.
	 */
	public abstract AbstractUser getOwner ();

	/**
	 * <p>
	 * Get the index of this room within the set of rooms to which it
	 * belongs.
	 * </p>
	 * <p>
	 * For user-created rooms, this is the index of the room number
	 * within the user's “house,” typically 0 for the first room, 1 for
	 * the yard, and 2 or more for additional rooms.
	 * </p>
	 * <p>
	 * The meaning of this index varies depending upon context;
	 * presently, it is only meaningful for user houses.
	 * </p>
	 * 
	 * @return the index of this room
	 */
	public abstract int getRoomIndex ();

	/**
	 * @return the file to load for the sky of this room
	 */
	public abstract String getSky ();

	/**
	 * Get the room's string title
	 * 
	 * @return the user-visible title of the room
	 */
	public abstract String getTitle ();

	/**
	 * @return the number of users in the room
	 */
	public abstract int getUserCount ();

	/**
	 * @param string the variable name for which the value is requested
	 * @return the value of that variable, if any, or null, if no such
	 *         variable is attached to this room
	 */
	public abstract String getVariable (final String string);

	/**
	 * Get the set of all variables which are attached to this room
	 * 
	 * @return room variables
	 */
	public abstract HashMap <String, String> getVariables ();

	/**
	 * @return The zone in which this Room is found
	 */
	public abstract AbstractZone getZone ();

	/**
	 * This is an overriding method.
	 * 
	 * @see java.lang.Object#hashCode()
	 */
	public abstract int hashCode ();

	/**
	 * <p>
	 * A “limbo” room is a room in which no public messaging is carried
	 * out. Users are unaware of one another's presence, comings and
	 * goings, and there are no public messages. The default “limbo”
	 * room is named “nowhere”
	 * </p>
	 * 
	 * @return true, if this is a limbo room
	 */
	public abstract boolean isLimbo ();

	/**
	 * @return true, if the sky is visible in this room; else, false
	 */
	public abstract boolean isSkyVisible ();

	/**
	 * Notify this room (and anyone in it) that someone has joined
	 * 
	 * @param thing the thing that has joined the room
	 */
	public abstract void join (final RoomListener thing);

	/**
	 * @param roomListener the thing which wants to stop listening to the room
	 */
	public abstract void part (RoomListener roomListener);

	/**
	 * Propagate a game event to every user in the room.
	 * 
	 * @param from WRITEME
	 * @param data WRITEME
	 * @throws JSONException if the action can't be represented in JSON
	 */
	public abstract void sendGameAction (
			final org.starhope.appius.user.User from,
			final JSONObject data) throws JSONException;

	/**
	 * @param from WRITEME
	 * @param speech WRITEME
	 */
	public abstract void sendPublicMessage (final AbstractUser from,
			final String speech);

	/**
	 * @param filename1 the filename to set
	 */
	public abstract void setFilename (final String filename1);

	/**
	 * @param b true, if this is a limbo room
	 */
	public abstract void setLimbo (final boolean b);

	/**
	 * @param moniker1 the moniker to set
	 */
	public abstract void setMoniker (final String moniker1);

	/**
	 * @param music1 the new background music
	 */
	public abstract void setMusic (final String music1);

	/**
	 * @param overlay1 the overlay to set
	 */
	public abstract void setOverlay (final String overlay1);

	/**
	 * TODO: document this method (brpocock, Jan 13, 2010)
	 *
	 * @param newHomeOwner new home owner
	 */
	void setOwner (AbstractUser newHomeOwner);

	/**
	 * WRITEME
	 */
	public abstract void setRoomVars ();

	/**
	 * @param sky1 the sky to set
	 */
	public abstract void setSky (final String sky1);

	/**
	 * @param skyVisible1 the skyVisible to set
	 */
	public abstract void setSkyVisible (final boolean skyVisible1);

	/**
	 * TODO: document this method (brpocock, Oct 5, 2009)
	 * 
	 * @param newTitle WRITEME
	 */
	public abstract void setTitle (final String newTitle);

	/**
	 * @param var A Hash type Entry object containing a key-value pair
	 *            to be used to set a variable.
	 */
	public abstract void setVariable (final Entry <String, String> var);

	/**
	 * Set a room variable. Room variables are transmitted to users upon
	 * joining a room (unless that room's “limbo” flag is set), and if
	 * they are changed, the changes propagate to everyone listening to
	 * that room (again, unless the room is in “limbo”)
	 * 
	 * @param varName the name of the room variable to alter
	 * @param varValue the new value
	 */
	public abstract void setVariable (final String varName,
			final String varValue);

	/**
	 * 
	 * @param map a map containing variables and
	 */
	public abstract void setVariables (final Map <String, String> map);

	/**
	 * @return the room's JSON representation
	 */
	public abstract JSONObject toJSON ();

}
