/**
 * <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.via;

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.game.AbstractRoom;
import org.starhope.appius.game.AppiusClaudiusCaecus;
import org.starhope.appius.game.GameEvent;
import org.starhope.appius.game.RoomListener;
import org.starhope.appius.types.AbstractZone;
import org.starhope.appius.user.AbstractUser;
import org.starhope.appius.user.User;

/**
 * 
 * WRITEME: The documentation for this type (RemoteRoom) is incomplete.
 * (brpocock, Jan 11, 2010)
 * 
 * @author brpocock
 * 
 */
public class RemoteRoom implements AbstractRoom,
		ViaMunita <AbstractRoom> {

	/**
	 * WRITEME: document this field (brpocock, Jan 13, 2010)
	 * 
	 * moniker (RemoteRoom)
	 */
	private final String moniker;
	/**
	 * WRITEME
	 */
	private final int remotePort;
	/**
	 * WRITEME
	 */
	private final String remoteServer;
	/**
	 * WRITEME
	 */
	private final String remoteZone;
	/**
	 * WRITEME: document this field (brpocock, Jan 13, 2010) roomID
	 * (RemoteRoom)
	 */
	private final int roomID;

	/**
	 * WRITEME
	 * 
	 * @param url WRITEME
	 */
	public RemoteRoom (final String url) {
		remoteServer = Via.getServerNameFromURL (url);
		remotePort = Via.getPortNumberFromURL (url);
		final String path = Via.getPathFromURL (url);
		if ( !path.startsWith ("Room/"))
			throw AppiusClaudiusCaecus.fatalBug ("URL is not a Room: "
					+ url);
		final String zoneAndRoom = path.substring (path
				.indexOf ("Room/") + 5);
		moniker = zoneAndRoom.substring (0, zoneAndRoom.indexOf ('/'));
		remoteZone = zoneAndRoom
				.substring (zoneAndRoom.indexOf ('/') + 2);
		roomID = ((Integer) Via.rpc (this, "getID")).intValue ();
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#add(org.starhope.appius.game.GameEvent)
	 */
	public void add (final GameEvent game) {
		Via.rpc (this, "add", game);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @param other another room to be compared against
	 * @return a slightly arbitrary sort order
	 * @see Comparable#compareTo(Object)
	 */
	public int compareTo (final AbstractRoom other) {
		return getDebugName ().compareTo (other.getDebugName ());
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#contains(AbstractUser)
	 */
	public boolean contains (final AbstractUser user) {
		return ((Boolean) Via.rpc (this, "contains", user))
				.booleanValue ();
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#deleteVariable(java.lang.String)
	 */
	public void deleteVariable (final String string) {
		Via.rpc (this, "deleteVariable", string);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#destroySelf()
	 */
	public void destroySelf () {
		Via.rpc (this, "destroySelf");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @param other WRITEME
	 * @return WRITEME
	 * @see Object#equals(Object)
	 */
	public boolean equals (final AbstractRoom other) {
		if (null == other) return false;
		if ( ! (other instanceof RemoteRoom)) return false;
		return other.getDebugName ().equals (getDebugName ());
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#flush()
	 */
	public void flush () {
		Via.rpc (this, "flush");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#fromJSON(org.json.JSONObject)
	 */
	public void fromJSON (final JSONObject jso) throws JSONException {
		Via.rpc (this, "fromJSON", jso);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getAllListeners()
	 */
	@SuppressWarnings ("unchecked")
	public Set <RoomListener> getAllListeners () {
		return (Set <RoomListener>) Via.rpc (this, "getAllListeners");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getAllUsers()
	 */
	@SuppressWarnings ("unchecked")
	public Collection <AbstractUser> getAllUsers () {
		return (Collection <AbstractUser>) Via
				.rpc (this, "getAllUsers");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getDebugName()
	 */
	public String getDebugName () {
		return "RemoteRoom:" + remoteServer + ":" + remotePort + "!"
				+ remoteZone + "!" + moniker;
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getFilename()
	 */
	public String getFilename () {
		return getVariable ("f");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getGameEvent()
	 */
	public GameEvent getGameEvent () {
		return (GameEvent) Via.rpc (this, "getGameEvent");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getId()
	 * @deprecated use {@link #getID()}
	 */
	@Deprecated
	public int getId () {
		return getID ();
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getID()
	 */
	public int getID () {
		return roomID;
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getListeners()
	 */
	@SuppressWarnings ("unchecked")
	public Collection <RoomListener> getListeners () {
		return (Collection <RoomListener>) Via.rpc (this,
				"getListeners");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getMaxUsers()
	 */
	public int getMaxUsers () {
		return ((Integer) Via.rpc (this, "getMaxUsers")).intValue ();
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getMoniker()
	 */
	public String getMoniker () {
		return moniker;
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getMusic()
	 */
	public String getMusic () {
		return getVariable ("m");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getName()
	 */
	public String getName () {
		return (String) Via.rpc (this, "getName");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getOverlay()
	 */
	public String getOverlay () {
		return getVariable ("w");
	}

	/**
	 * @see org.starhope.appius.game.AbstractRoom#getOwner()
	 */
	public AbstractUser getOwner () {
		final String ownerName = getVariable ("homeOwner");
		if (null == ownerName || "".equals (ownerName)) return null;
		return User.getByLogin (ownerName);
	}

	/**
	 * @see org.starhope.appius.game.AbstractRoom#getRoomIndex()
	 */
	public int getRoomIndex () {
		return ((Integer) Via.rpc (this, "getRoomIndex")).intValue ();
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getSky()
	 */
	public String getSky () {
		return getVariable ("s");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getTitle()
	 */
	public String getTitle () {
		return (String) Via.rpc (this, "getTitle");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getUserCount()
	 */
	public int getUserCount () {
		return ((Integer) Via.rpc (this, "getUserCount")).intValue ();
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getVariable(java.lang.String)
	 */
	public String getVariable (final String string) {
		return (String) Via.rpc (this, "getVariable", string);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getVariables()
	 */
	@SuppressWarnings ("unchecked")
	public HashMap <String, String> getVariables () {
		return (HashMap <String, String>) Via
				.rpc (this, "getVariables");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.via.ViaMunita#getViaAppiaHostname()
	 */
	public String getViaAppiaHostname () {
		return remoteServer;
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.via.ViaMunita#getViaAppiaRemoteEndpointID()
	 */
	public String getViaAppiaRemoteEndpointID () {
		return "Room/" + moniker + "@" + remoteZone;
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.via.ViaMunita#getViaAppiaServerPort()
	 */
	public int getViaAppiaServerPort () {
		return remotePort;
	}

	/**
	 * @see org.starhope.appius.via.ViaMunita#getViaPeerClass()
	 */
	public Class <AbstractRoom> getViaPeerClass () {
		return AbstractRoom.class;
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#getZone()
	 */
	public AbstractZone getZone () {
		return RemoteZone.getByName (remoteZone);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#isLimbo()
	 */
	public boolean isLimbo () {
		return ((Boolean) Via.rpc (this, "isLimbo")).booleanValue ();
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#isSkyVisible()
	 */
	public boolean isSkyVisible () {
		return ((Boolean) Via.rpc (this, "isSkyVisible"))
				.booleanValue ();
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#join(RoomListener)
	 */
	public void join (final RoomListener who) {
		Via.rpc (this, "join", who);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#part(RoomListener)
	 */
	public void part (final RoomListener thing) {
		Via.rpc (this, "part", thing);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#sendGameAction(org.starhope.appius.user.User,
	 *      org.json.JSONObject)
	 */
	public void sendGameAction (final User from, final JSONObject data)
		throws JSONException {
		Via.rpc (this, "sendGameAction", from, data);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#sendPublicMessage(org.starhope.appius.user.AbstractUser,
	 *      java.lang.String)
	 */
	public void sendPublicMessage (final AbstractUser from,
			final String speech) {
		Via.rpc (this, "sendPublicMessage", from, speech);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#setFilename(java.lang.String)
	 */
	public void setFilename (final String filename1) {
		Via.rpc (this, "setFilename", filename1);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#setLimbo(boolean)
	 */
	public void setLimbo (final boolean b) {
		Via.rpc (this, "setLimbo", b);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#setMoniker(java.lang.String)
	 */
	public void setMoniker (final String moniker1) {
		Via.rpc (this, "setMoniker", moniker1);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#setMusic(java.lang.String)
	 */
	public void setMusic (final String music1) {
		Via.rpc (this, "setMusic", music1);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#setOverlay(java.lang.String)
	 */
	public void setOverlay (final String overlay1) {
		Via.rpc (this, "setOverlay", overlay1);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#setOwner(org.starhope.appius.user.AbstractUser)
	 */
	public void setOwner (final AbstractUser newHomeOwner) {
		Via.rpc (this, "setOwner", newHomeOwner);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#setRoomVars()
	 */
	public void setRoomVars () {
		Via.rpc (this, "setRoomVars");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#setSky(java.lang.String)
	 */
	public void setSky (final String sky1) {
		Via.rpc (this, "setSky");
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#setSkyVisible(boolean)
	 */
	public void setSkyVisible (final boolean skyVisible1) {
		Via.rpc (this, "setSkyVisible", skyVisible1);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#setTitle(java.lang.String)
	 */
	public void setTitle (final String newTitle) {
		Via.rpc (this, "setTitle", newTitle);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#setVariable(java.util.Map.Entry)
	 */
	public void setVariable (final Entry <String, String> var) {
		Via.rpc (this, "setVariable", var);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#setVariable(java.lang.String,
	 *      java.lang.String)
	 */
	public void setVariable (final String varName, final String varValue) {
		Via.rpc (this, "setVariable", varName, varValue);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#setVariables(java.util.Map)
	 */
	public void setVariables (final Map <String, String> map) {
		Via.rpc (this, "setVariables", map);
	}

	/**
	 * This is an overriding method.
	 * 
	 * @see org.starhope.appius.game.AbstractRoom#toJSON()
	 */
	public JSONObject toJSON () {
		return (JSONObject) Via.rpc (this, "toJSON");
	}

}
