/*******************************************************************************
 * Copyright (c) 2004, 2009 Composent, Inc. and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *    Composent, Inc. - initial API and implementation
 *    Jacek Pospychala <jacek.pospychala@pl.ibm.com> - bug 197604, 197329
 ******************************************************************************/
package org.eclipse.ecf.internal.provider.irc.container;

import java.net.InetSocketAddress;
import java.util.*;
import org.eclipse.ecf.core.*;
import org.eclipse.ecf.core.events.*;
import org.eclipse.ecf.core.identity.*;
import org.eclipse.ecf.core.security.IConnectContext;
import org.eclipse.ecf.core.util.ECFException;
import org.eclipse.ecf.internal.provider.irc.Activator;
import org.eclipse.ecf.internal.provider.irc.Messages;
import org.eclipse.ecf.internal.provider.irc.datashare.IIRCDatashareContainer;
import org.eclipse.ecf.internal.provider.irc.datashare.IRCDatashareContainer;
import org.eclipse.ecf.internal.provider.irc.identity.IRCID;
import org.eclipse.ecf.internal.provider.irc.identity.IRCNamespace;
import org.eclipse.ecf.presence.chatroom.*;
import org.eclipse.ecf.presence.history.IHistory;
import org.eclipse.ecf.presence.history.IHistoryManager;
import org.eclipse.ecf.presence.im.IChatMessage.Type;
import org.eclipse.ecf.presence.im.IChatMessageSender;
import org.eclipse.equinox.concurrent.future.TimeoutException;
import org.eclipse.osgi.util.NLS;
import org.schwering.irc.lib.*;
import org.schwering.irc.lib.ssl.SSLIRCConnection;

/**
 * IRC 'root' container implementation. This class implements the
 * IChatRoomManager and the IChatRoomContainer interfaces, allowing it to
 * function as both a manager of IRC channels and as an IRC channel itself.
 * 
 */
public class IRCRootContainer extends IRCAbstractContainer implements
		IContainer, IChatMessageSender, IChatRoomInvitationSender,
		IChatRoomManager, IChatRoomContainer, IRCMessageChannel,
		IChatRoomContainerOptionsAdapter {

	private static final long CONNECT_TIMEOUT = new Long(System.getProperty(
			"org.eclipse.ecf.provider.irc.connectTimeout", "60000"))
			.longValue();

	protected IRCConnection connection = null;

	protected ReplyHandler replyHandler = null;

	protected Map channels = new HashMap();

	protected String username;

	protected String encoding = null;

	private ArrayList invitationListeners;

	protected Object connectLock = new Object();
	protected boolean connectWaiting = false;
	protected Exception connectException = null;

	/**
	 * The datashare container implementation owned by this container.
	 */
	private IIRCDatashareContainer datashareContainer;

	/**
	 * Used for determining whether the USERHOST reply should be hijacked or
	 * not.
	 */
	private boolean retrieveUserhost;

	public IRCRootContainer(ID localID) throws IDCreateException {
		this.localID = localID;
		this.unknownID = IDFactory.getDefault().createStringID(
				Messages.IRCRootContainer_0);
		this.replyHandler = new ReplyHandler();
		invitationListeners = new ArrayList();
		datashareContainer = createDatashareContainer();
	}

	/**
	 * Creates and returns a datashare container implementation.
	 * 
	 * @return a datashare container implementation for this container, or
	 *         <code>null</code> if it could not be created
	 */
	private IIRCDatashareContainer createDatashareContainer() {
		if (hasDatashare() && hasNIO()) {
			return new IRCDatashareContainer(this);
		}
		return null;
	}

	/**
	 * Checks and returns whether the datashare NIO APIs are available in the
	 * current OSGi environment.
	 * 
	 * @return <code>true</code> if the datashare NIO APIs are available,
	 *         <code>false</code> otherwise
	 */
	private boolean hasDatashare() {
		return Activator.getDefault().hasDatashare();
	}

	/**
	 * Checks and returns there is Java 1.4 NIO support in the current Java
	 * runtime environment.
	 * 
	 * @return <code>true</code> if the Java 1.4 NIO APIs are available,
	 *         <code>false</code> otherwise
	 */
	private boolean hasNIO() {
		try {
			Class.forName("java.nio.channels.SocketChannel"); //$NON-NLS-1$
			return true;
		} catch (ClassNotFoundException e) {
			return false;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ecf.core.IContainer#connect(org.eclipse.ecf.core.identity.ID,
	 * org.eclipse.ecf.core.security.IConnectContext)
	 */
	public void connect(ID connectID, IConnectContext connectContext)
			throws ContainerConnectException {
		if (connection != null)
			throw new ContainerConnectException(
					Messages.IRCRootContainer_Exception_Already_Connected);
		if (connectID == null)
			throw new ContainerConnectException(
					Messages.IRCRootContainer_Exception_TargetID_Null);
		if (!(connectID instanceof IRCID))
			throw new ContainerConnectException(NLS.bind(
					Messages.IRCRootContainer_Exception_TargetID_Wrong_Type,
					new Object[] { targetID, IRCID.class.getName() }));
		if (connectWaiting)
			throw new ContainerConnectException(
					Messages.IRCRootContainer_Connecting);

		fireContainerEvent(new ContainerConnectingEvent(this.getID(),
				connectID, connectContext));
		// Get password via callback in connectContext
		String pw = getPasswordFromConnectContext(connectContext);
		IRCID tID = (IRCID) connectID;
		String host = tID.getHost();
		int port = tID.getPort();
		String pass = pw;
		String nick = tID.getUser();
		String user = nick;
		this.username = user;
		String name = null;
		boolean ssl = false;
		if (!ssl) {
			connection = new IRCConnection(host, new int[] { port }, pass,
					nick, user, name);
		} else {
			connection = new SSLIRCConnection(host, new int[] { port }, pass,
					nick, user, name);
		}
		// connection setup
		connection.addIRCEventListener(getIRCEventListener());
		connection.setPong(true);
		connection.setDaemon(false);
		connection.setColors(true);
		if (encoding != null)
			connection.setEncoding(encoding);
		trace(Messages.IRCRootContainer_Connecting_To + targetID);
		synchronized (connectLock) {
			connectWaiting = true;
			connectException = null;
			try {
				connection.connect();
				long timeout = CONNECT_TIMEOUT + System.currentTimeMillis();
				while (connectWaiting && (timeout > System.currentTimeMillis())) {
					connectLock.wait(2000);
				}
				if (connectWaiting)
					throw new TimeoutException(NLS.bind(
							Messages.IRCRootContainer_Connect_Timeout,
							tID.getName()), CONNECT_TIMEOUT);
				if (connectException != null)
					throw connectException;
				this.targetID = tID;
				fireContainerEvent(new ContainerConnectedEvent(getID(),
						this.targetID));

				if (datashareContainer != null) {
					// now that we've connected successfully, we send a USERHOST
					// message to the server so that we can attempt to retrieve
					// our current IP
					retrieveUserhost = true;
					connection.doUserhost(nick);
				}
			} catch (Exception e) {
				this.targetID = null;
				throw new ContainerConnectException(NLS.bind(
						Messages.IRCRootContainer_Exception_Connect_Failed,
						connectID.getName()), e);
			} finally {
				connectWaiting = false;
				connectException = null;
			}
		}
	}

	protected void handleDisconnected() {
		for (Iterator i = channels.values().iterator(); i.hasNext();) {
			IRCChannelContainer c = (IRCChannelContainer) i.next();
			c.disconnect();
		}
		fireContainerEvent(new ContainerDisconnectedEvent(getID(), targetID));
		channels.clear();
	}

	protected void handleErrorIfConnecting(String message) {
		synchronized (connectLock) {
			if (connectWaiting)
				this.connectException = new Exception(message);
		}
	}

	protected IRCEventListener getIRCEventListener() {
		return new IRCEventListener() {
			public void onRegistered() {
				trace("handleOnRegistered()"); //$NON-NLS-1$
				synchronized (connectLock) {
					connectWaiting = false;
					connectLock.notify();
				}
			}

			public void onDisconnected() {
				trace("handleOnDisconnected()"); //$NON-NLS-1$
				fireContainerEvent(new ContainerDisconnectingEvent(getID(),
						targetID));
				synchronized (connectLock) {
					if (connectWaiting) {
						if (connectException == null)
							connectException = new Exception(
									Messages.IRCRootContainer_Exception_Unexplained_Disconnect);
						connectWaiting = false;
						connectLock.notify();
					}
				}
				if (targetID != null) {
					showMessage(null, NLS.bind(
							Messages.IRCRootContainer_Disconnected,
							targetID.getName()));
					handleDisconnected();
				}
			}

			public void onError(String arg0) {
				trace("handleOnError(" + arg0 + ")"); //$NON-NLS-1$ //$NON-NLS-2$
				showMessage(null,
						NLS.bind(Messages.IRCRootContainer_Error, arg0));
				handleErrorIfConnecting(arg0);
			}

			public void onError(int arg0, String arg1) {
				String msg = arg0 + "," + arg1; //$NON-NLS-1$
				trace("handleOnError(" + msg + ")"); //$NON-NLS-1$ //$NON-NLS-2$
				showMessage(null,
						NLS.bind(Messages.IRCRootContainer_Error, msg));
				handleErrorIfConnecting(arg0 + msg);
			}

			public void onInvite(String arg0, IRCUser arg1, String arg2) {
				handleInvite(createIDFromString(arg0),
						createIDFromString(arg1.getNick()));
			}

			public void onJoin(String arg0, IRCUser arg1) {
				trace("handleOnJoin(" + arg0 + "," + arg1 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				IRCChannelContainer container = getChannel(arg0);
				if (container != null) {
					container.setIRCUser(arg1);
				}
			}

			public void onKick(String channelName, IRCUser kicker,
					String kicked, String reason) {
				trace("handleOnKick(" + channelName + "," + kicker + "," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
						+ kicked + "," + reason + ")"); //$NON-NLS-1$ //$NON-NLS-2$
				// retrieve the channel that this kick is happening at
				IRCChannelContainer channel = getChannel(channelName);
				if (channel != null) {
					// display a message to indicate that a user has been kicked
					// from the channel
					showMessage(channelName, NLS.bind(
							Messages.IRCRootContainer_UserKicked, new Object[] {
									kicker.getNick(), kicked, channelName,
									reason }));
					// check if we are the ones that have been kicked
					if (kicked.equals(((IRCID) targetID).getUsername())) {
						// fire disconnection events for this channel container
						channel.fireContainerEvent(new ContainerDisconnectingEvent(
								channel.getID(), channel.targetID));
						channel.firePresenceListeners(false,
								new String[] { kicked });
						channel.fireContainerEvent(new ContainerDisconnectedEvent(
								channel.getID(), channel.targetID));
					} else {
						channel.firePresenceListeners(false,
								new String[] { kicked });
					}
				}
			}

			public void onMode(String arg0, IRCUser arg1, IRCModeParser arg2) {
				trace("handleOnMode(" + arg0 + "," + arg1 + "," + arg2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
			}

			public void onMode(IRCUser arg0, String arg1, String arg2) {
				trace("handleOnMode(" + arg0 + "," + arg1 + "," + arg2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
			}

			public void onNick(IRCUser arg0, String arg1) {
				trace("handleOnNick(" + arg0 + "," + arg1 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			}

			public void onNotice(String arg0, IRCUser arg1, String arg2) {
				trace("handleOnNotice(" + arg0 + "," + arg1 + "," + arg2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
				showMessage(arg0, arg2);
			}

			public void onPart(String arg0, IRCUser arg1, String arg2) {
				trace("handleOnPart(" + arg0 + "," + arg1 + "," + arg2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
				IRCChannelContainer channel = (IRCChannelContainer) channels
						.get(arg0);
				if (channel != null) {
					channel.firePresenceListeners(false,
							new String[] { getIRCUserName(arg1) });
				}
			}

			public void onPing(String arg0) {
				trace("handleOnPing(" + arg0 + ")"); //$NON-NLS-1$ //$NON-NLS-2$
				synchronized (IRCRootContainer.this) {
					if (connection != null) {
						connection.doPong(arg0);
					}
				}
			}

			public void onPrivmsg(String arg0, IRCUser arg1, String arg2) {
				trace("handleOnPrivmsg(" + arg0 + "," + arg1 + "," + arg2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$ 
				if (arg2.equals("\01VERSION\01")) { //$NON-NLS-1$
					showMessage(null, NLS.bind(
							Messages.IRCRootContainer_CTCP_VERSION_Request,
							arg1.toString()));
				} else if (arg2.startsWith("\01ECF ") && arg2.endsWith("\01")) { //$NON-NLS-1$ //$NON-NLS-2$
					if (datashareContainer != null) {
						// special ECF message, retrieve the ip address of the
						// remote peer and initiate a socket connection
						String identifier = arg2
								.substring(5, arg2.length() - 1);
						StringTokenizer tokenizer = new StringTokenizer(
								identifier, ":"); //$NON-NLS-1$
						datashareContainer.enqueue(new InetSocketAddress(
								tokenizer.nextToken(), Integer
										.parseInt(tokenizer.nextToken())));
					}
				} else {
					showMessage(arg0, arg1.toString(), arg2);
				}

			}

			public void onQuit(IRCUser arg0, String arg1) {
				trace("handleOnQuit(" + arg0 + "," + arg1 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
				for (Iterator i = channels.values().iterator(); i.hasNext();) {
					IRCChannelContainer container = (IRCChannelContainer) i
							.next();
					container.handleUserQuit(getIRCUserName(arg0));
				}
			}

			public void onReply(int arg0, String arg1, String arg2) {
				trace("handleOnReply(" + arg0 + "|" + arg1 + "|" + arg2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
				replyHandler.handleReply(arg0, arg1, arg2);
			}

			public void onTopic(String arg0, IRCUser arg1, String arg2) {
				trace("handleOnTopic(" + arg0 + "," + arg1 + "," + arg2 + ")"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
				handleSetSubject(arg0, arg1, arg2);
			}

			public void unknown(String arg0, String arg1, String arg2,
					String arg3) {
				trace("handleUnknown(" + arg0 + "," + arg1 + "," + arg2 + "," //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
						+ arg3 + ")"); //$NON-NLS-1$
				showMessage(null, NLS.bind(
						Messages.IRCRootContainer_Unknown_Message,
						new Object[] { arg0, arg1, arg2, arg3 }));
			}
		};
	}

	protected String getIRCUserName(IRCUser user) {
		return user == null ? null : user.toString();
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ecf.core.IContainer#disconnect()
	 */
	public void disconnect() {
		if (connection != null) {
			connection.close();
			connection = null;
			targetID = null;
			retrieveUserhost = false;
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ecf.core.IContainer#getAdapter(java.lang.Class)
	 */
	public Object getAdapter(Class serviceType) {
		if (serviceType == null) {
			return null;
		} else if (serviceType.isInstance(this)) {
			return this;
		} else if (datashareContainer != null
				&& serviceType.isInstance(datashareContainer)) {
			return datashareContainer;
		}
		return null;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.ecf.core.IContainer#getConnectNamespace()
	 */
	public Namespace getConnectNamespace() {
		return IDFactory.getDefault().getNamespaceByName(
				IRCNamespace.IRC_SCHEME);
	}

	public IChatRoomInfo getChatRoomInfo(final String roomName) {
		if (roomName == null)
			return new IChatRoomInfo() {
				public IChatRoomContainer createChatRoomContainer()
						throws ContainerCreateException {
					return IRCRootContainer.this;
				}

				public ID getConnectedID() {
					return IRCRootContainer.this.getConnectedID();
				}

				public String getDescription() {
					return ""; //$NON-NLS-1$
				}

				public String getName() {
					return ROOT_ROOMNAME;
				}

				public int getParticipantsCount() {
					return 0;
				}

				public ID getRoomID() {
					return getSystemID();
				}

				public String getSubject() {
					return ""; //$NON-NLS-1$
				}

				public boolean isModerated() {
					return false;
				}

				public boolean isPersistent() {
					return false;
				}

				public boolean requiresPassword() {
					return false;
				}

				public Object getAdapter(Class adapter) {
					return null;
				}
			};
		return new IChatRoomInfo() {
			public IChatRoomContainer createChatRoomContainer()
					throws ContainerCreateException {
				try {
					IRCChannelContainer newChannelContainer = new IRCChannelContainer(
							IRCRootContainer.this, IDFactory.getDefault()
									.createGUID());
					addChannel(roomName, newChannelContainer);
					return newChannelContainer;
				} catch (Exception e) {
					throw new ContainerCreateException(
							Messages.IRCRootContainer_Exception_Create_ChatRoom,
							e);
				}
			}

			public ID getConnectedID() {
				return IRCRootContainer.this.getConnectedID();
			}

			public String getDescription() {
				return ""; //$NON-NLS-1$
			}

			public String getName() {
				return roomName;
			}

			public int getParticipantsCount() {
				return 0;
			}

			public ID getRoomID() {
				return createIDFromString(roomName);
			}

			public String getSubject() {
				return ""; //$NON-NLS-1$
			}

			public boolean isModerated() {
				return false;
			}

			public boolean isPersistent() {
				return false;
			}

			public boolean requiresPassword() {
				return false;
			}

			public Object getAdapter(Class adapter) {
				return null;
			}
		};
	}

	public IChatRoomInfo[] getChatRoomInfos() {
		return new IChatRoomInfo[0];
	}

	public IChatRoomManager[] getChildren() {
		return new IChatRoomManager[0];
	}

	public IChatRoomManager getParent() {
		return null;
	}

	public void addChatRoomParticipantListener(
			IChatRoomParticipantListener participantListener) {
		// for root container, no participant listening
	}

	public void removeChatRoomParticipantListener(
			IChatRoomParticipantListener participantListener) {
		// for root container, no participant listening
	}

	public IChatRoomMessageSender getChatRoomMessageSender() {
		return new IChatRoomMessageSender() {
			public void sendMessage(String message) throws ECFException {
				if (isCommand(message))
					parseCommandAndSend(message, null, null);
				else
					showErrorMessage(null, NLS.bind(
							Messages.IRCRootContainer_Command_Error, message,
							COMMAND_PREFIX));
			}
		};
	}

	/**
	 * Returns string from the buffer beginning up to nearest COMMAND_DELIM.
	 * Strips trailing COMMAND_DELIMs.
	 * 
	 * @param buffer
	 * @return String up to first COMMAND_DELIM occurrence in buffer.
	 */
	protected String nextToken(StringBuffer buffer) {
		if (buffer.length() == 0) {
			return null;
		}

		String token;

		int index = buffer.indexOf(COMMAND_DELIM);

		if (index == -1) { // no delim until the end of buffer
			token = buffer.toString();
			buffer.delete(0, buffer.length());
			return token;
		}

		token = buffer.substring(0, index);

		/*
		 * if (token.length() == buffer.length()) { //index = token.length() -
		 * 1; }
		 */

		// trim trailing command delims
		while ((buffer.length() > index)
				&& (buffer.indexOf(COMMAND_DELIM, index) == index)) {
			index += COMMAND_DELIM.length();
		}
		if (index > 0) {
			buffer.delete(0, index);
		}

		return token;
	}

	protected void parseCommandAndSend(String commandMessage,
			String channelName, String ircUser) {
		synchronized (this) {
			if (connection != null) {
				try {
					String lowerCase = commandMessage.toLowerCase();
					StringBuffer command = new StringBuffer(commandMessage);

					if (lowerCase.startsWith("/msg ")) { //$NON-NLS-1$
						commandMessage = commandMessage.substring(5);
						int index = commandMessage.indexOf(COMMAND_DELIM);
						if (index != -1) {
							connection.doPrivmsg(
									commandMessage.substring(0, index),
									commandMessage.substring(index + 1));
						}
					} else if (lowerCase.startsWith("/privmsg ")) { //$NON-NLS-1$
						commandMessage = commandMessage.substring(9);
						int index = commandMessage.indexOf(COMMAND_DELIM);
						if (index != -1) {
							connection.doPrivmsg(
									commandMessage.substring(0, index),
									commandMessage.substring(index + 1));
						}
					} else if (lowerCase.startsWith("/op ")) { //$NON-NLS-1$
						nextToken(command); // skip command

						String nick = nextToken(command);

						if (nick != null) {
							connection.doMode(channelName, "+o " + nick); //$NON-NLS-1$
						}
					} else if (lowerCase.startsWith("/dop ")) { //$NON-NLS-1$
						nextToken(command); // skip command

						String nick = nextToken(command);

						if (nick != null) {
							connection.doMode(channelName, "-o " + nick); //$NON-NLS-1$
						}
					} else if (lowerCase.startsWith("/ban ")) { //$NON-NLS-1$
						nextToken(command); // skip command

						String nick = nextToken(command);

						if (nick != null) {
							connection.doMode(channelName, "+b " + nick); //$NON-NLS-1$
						}
					} else if (lowerCase.startsWith("/unban ")) { //$NON-NLS-1$
						nextToken(command); // skip command

						String nick = nextToken(command);

						if (nick != null) {
							connection.doMode(channelName, "-b " + nick); //$NON-NLS-1$ 
						}
					} else if (lowerCase.startsWith("/kick ")) { //$NON-NLS-1$
						nextToken(command); // skip command

						String nick = nextToken(command);

						if (nick.startsWith("#")) { //$NON-NLS-1$
							channelName = nick;
							nick = nextToken(command);
						}

						String comment = command.toString(); // rest of command

						if (comment.length() > 0) {
							connection.doKick(channelName, nick, comment);
						} else {
							connection.doKick(channelName, nick);
						}
					} else if (lowerCase.startsWith("/mode ")) { //$NON-NLS-1$
						commandMessage = commandMessage.substring(6);
						int index = commandMessage.indexOf(COMMAND_DELIM);
						if (index != -1) {
							connection.doMode(channelName, commandMessage);
						}
					} else if (lowerCase.startsWith("/me ")) { //$NON-NLS-1$
						nextToken(command); // skip command

						String message = command.toString();
						if (message.length() > 0) {
							message = "\01ACTION " + message + "\01"; //$NON-NLS-1$ //$NON-NLS-2$
							connection.doPrivmsg(channelName, message);
							showMessage(channelName, ircUser, message);
						}
					} else {
						String[] tokens = parseCommandTokens(commandMessage);
						handleCommandMessage(tokens, channelName);
					}
				} catch (Exception e) {
					showErrorMessage(channelName, NLS.bind(
							Messages.IRCRootContainer_Exception_Parse,
							new Object[] { e.getClass().getName(),
									e.getLocalizedMessage() }));
					traceStack(e, "PARSE ERROR: " + commandMessage); //$NON-NLS-1$
				}
			} else {
				trace("parseMessageAndSend(" + commandMessage //$NON-NLS-1$
						+ ") Not connected for IRCContainer " + getID()); //$NON-NLS-1$
			}
		}
	}

	private synchronized void handleCommandMessage(String[] tokens,
			String channelName) {
		// Look at first one and switch
		String origCommand = tokens[0];
		String command = origCommand;
		while (command.startsWith(COMMAND_PREFIX))
			command = command.substring(1);
		String[] args = new String[tokens.length - 1];
		System.arraycopy(tokens, 1, args, 0, tokens.length - 1);
		if (command.equalsIgnoreCase(JOIN_COMMAND)) {
			if (args.length > 1) {
				connection.doJoin(args[0], args[1]);
			} else if (args.length > 0) {
				connection.doJoin(args[0]);
			}
		} else if (command.equalsIgnoreCase(LIST_COMMAND)) {
			if (args.length > 0) {
				connection.doList(args[0]);
			} else
				connection.doList();
		} else if (command.equalsIgnoreCase(PART_COMMAND)) {
			if (args.length > 1) {
				connection.doPart(args[0], args[1]);
			} else if (args.length > 0) {
				connection.doPart(args[0]);
			}
		} else if (command.equalsIgnoreCase(NICK_COMMAND)) {
			if (args.length > 0) {
				connection.doNick(args[0]);
			}
		} else if (command.equalsIgnoreCase(NOTICE_COMMAND)) {
			if (args.length > 1) {
				connection.doNotice(args[0], args[1]);
			}
		} else if (command.equalsIgnoreCase(WHOIS_COMMAND)) {
			if (args.length > 0) {
				connection.doWhois(args[0]);
			}
		} else if (command.equalsIgnoreCase(QUIT_COMMAND)) {
			if (args.length > 0) {
				connection.doQuit(args[0]);
			} else {
				connection.doQuit();
			}
		} else if (command.equalsIgnoreCase(AWAY_COMMAND)) {
			if (args.length > 0) {
				connection.doAway(args[0]);
			} else {
				connection.doAway();
			}
		} else if (command.equalsIgnoreCase(TOPIC_COMMAND)) {
			if (args.length > 1) {
				StringBuffer sb = new StringBuffer();
				for (int i = 1; i < args.length; i++) {
					if (i > 1) {
						sb.append(COMMAND_DELIM);
					}
					sb.append(args[i]);
				}
				connection.doTopic(args[0], sb.toString());
			} else if (args.length > 0) {
				connection.doTopic(args[0]);
			}
		} else if (command.equalsIgnoreCase(INVITE_COMMAND)) {
			if (args.length > 1) {
				connection.doInvite(args[0], args[1]);
			}
		} else {
			String msg = NLS
					.bind(Messages.IRCRootContainer_Command_Unrecognized,
							origCommand);
			trace(msg + " in IRCContainer: " + getID()); //$NON-NLS-1$
			showErrorMessage(channelName, msg);
		}
	}

	protected void handleInvite(ID channelID, ID fromID) {
		synchronized (invitationListeners) {
			for (int i = 0; i < invitationListeners.size(); i++) {
				IChatRoomInvitationListener icril = (IChatRoomInvitationListener) invitationListeners
						.get(i);
				icril.handleInvitationReceived(channelID, fromID, null, null);
			}
		}
	}

	protected IRCChannelContainer getChannel(String channel) {
		if (channel == null)
			return null;
		IRCChannelContainer container = getContainerForChannel(channel);
		if (container == null)
			return null;
		return container;
	}

	protected void showMessage(String channel, String msg) {
		IRCChannelContainer msgChannel = getChannel(channel);
		if (msgChannel != null)
			msgChannel.fireChatRoomMessageEvent(createIDFromString(channel),
					msg);
		else
			fireChatRoomMessageEvent((channel == null) ? getSystemID()
					: createIDFromString(channel), msg);
	}

	protected void showMessage(String channel, String user, String msg) {
		IRCChannelContainer msgChannel = getChannel(channel);
		if (msgChannel != null) {
			msgChannel.fireChatRoomMessageEvent(createIDFromString(user), msg);
		} else {
			fireChatMessageEvent(createIDFromString(user), msg);
			for (Iterator it = channels.values().iterator(); it.hasNext();) {
				msgChannel = (IRCChannelContainer) it.next();
				msgChannel.fireChatMessageEvent(createIDFromString(user), msg);
			}
		}
	}

	void showErrorMessage(String channel, String msg) {
		IRCChannelContainer msgChannel = getChannel(channel);
		if (msgChannel != null)
			msgChannel.fireChatRoomMessageEvent(
					(username == null) ? getSystemID()
							: createIDFromString(username), msg);
		else
			fireChatRoomMessageEvent((username == null) ? getSystemID()
					: createIDFromString(username), msg);
	}

	ID getSystemID() {
		if (targetID == null)
			return unknownID;
		try {
			return IDFactory.getDefault().createStringID(
					((IRCID) targetID).getHost());
		} catch (IDCreateException e) {
			Activator.log(
					"ID creation exception in IRCContainer.getSystemID()", e); //$NON-NLS-1$
			return unknownID;
		}
	}

	protected void handle353Reply(String channel, String[] strings) {
		IRCChannelContainer container = getChannel(channel);
		if (container == null) {
			showMessage(null,
					NLS.bind(Messages.IRCRootContainer_353_Error, channel));
		} else
			container.firePresenceListeners(true, strings);
	}

	protected class ReplyHandler {
		public void handleReply(int code, String arg1, String arg2) {
			String[] users = parseUsers(arg1);
			switch (code) {
			case 353:
				handle353Reply(users[2], parseUserNames(arg2));
				break;
			case 311:
				showMessage(null,
						NLS.bind(Messages.IRCRootContainer_Whois, users[1]));
				showMessage(null, trimUsername(users[2]) + "@" + users[3]); //$NON-NLS-1$
				break;
			case 312:
				showMessage(null, NLS.bind(Messages.IRCRootContainer_Server,
						new Object[] { users[2], arg2 }));
				break;
			case 317:
				showMessage(null,
						NLS.bind(Messages.IRCRootContainer_Idle, users[2]));
				break;
			case 318:
				showMessage(null, Messages.IRCRootContainer_Whois_End);
				break;
			case 319:
				showMessage(null,
						NLS.bind(Messages.IRCRootContainer_Channels, arg2));
				break;
			case 320:
				break;
			case 331:
			case 332:
				// Subject changes
				String[] args = parseCommandTokens(arg1);
				String channel = (args.length == 2) ? args[1]
						: ((args.length == 1) ? args[0] : null);
				handleSetSubject(channel, null, arg2);
				break;
			case 302:
				if (retrieveUserhost) {
					if (datashareContainer != null) {
						// set the retrieved ip address from the
						arg2 = arg2.trim();
						String ip = arg2.substring(arg2.lastIndexOf('@') + 1);
						datashareContainer.setIP(ip);
					}
					retrieveUserhost = false;
					break;
				}
			default:
				// first user always expected to be us
				if (users.length < 2)
					showMessage(null, arg2);
				else {
					showMessage(users[1], concat(users, 2, arg2));
				}
			}
		}

		private String trimUsername(String un) {
			int eq = un.indexOf('=');
			return un.substring(eq + 1);
		}
	}

	protected void handleSetSubject(String channelName, IRCUser user,
			String newSubject) {
		IRCChannelContainer channel = (IRCChannelContainer) channels
				.get(channelName);
		if (channel == null) {
			showMessage(null, newSubject);
			fireSubjectListeners(null, newSubject);
		} else {
			String nickname = (user == null) ? null : user.getNick();
			ID fromID = (user == null) ? null
					: createIDFromString(getIRCUserName(user));
			// Put out message to channel
			if (nickname == null)
				showMessage(channelName, newSubject);
			else
				showMessage(channelName, NLS.bind(
						Messages.IRCRootContainer_TopicChange, new Object[] {
								nickname, newSubject }));
			// Also notify subject listeners
			channel.fireSubjectListeners(fromID, newSubject);
		}
	}

	protected void doJoinChannel(String channelName, String key) {
		if (connection != null) {
			if (key == null || key.equals("")) { //$NON-NLS-1$
				connection.doJoin(channelName);
			} else {
				connection.doJoin(channelName, key);
			}
		}
	}

	protected void doPartChannel(String channelName) {
		if (connection != null) {
			connection.doPart(channelName);
		}
	}

	protected void doSendChannelMessage(String channelName, String ircUser,
			String msg) {
		if (connection != null) {
			// If it's a command,
			if (isCommand(msg)) {
				parseCommandAndSend(msg, channelName, ircUser);
			} else {
				connection.doPrivmsg(channelName, msg);
				showMessage(channelName, ircUser, msg);
			}
		}
	}

	protected void doSendSubjectChangeMessage(String channelName, String topic)
			throws ECFException {
		if (connection == null)
			throw new ECFException(
					Messages.IRCRootContainer_Exception_Unexplained_Disconnect);
		connection.doTopic(channelName, topic);
	}

	protected void addChannel(String channel, IRCChannelContainer container) {
		channels.put(channel, container);
	}

	protected IRCChannelContainer getContainerForChannel(String channel) {
		return (IRCChannelContainer) channels.get(channel);
	}

	protected void removeChannel(String channel) {
		channels.remove(channel);
	}

	public boolean setEncoding(String encoding) {
		if (connection == null) {
			this.encoding = encoding;
			return true;
		}
		return false;
	}

	public void addInvitationListener(IChatRoomInvitationListener listener) {
		if (listener != null) {
			synchronized (invitationListeners) {
				if (!invitationListeners.contains(listener)) {
					invitationListeners.add(listener);
				}
			}
		}
	}

	public void removeInvitationListener(IChatRoomInvitationListener listener) {
		if (listener != null) {
			synchronized (invitationListeners) {
				invitationListeners.remove(listener);
			}
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ecf.presence.chatroom.IChatRoomManager#createChatRoom(java
	 * .lang.String, java.util.Map)
	 */
	public IChatRoomInfo createChatRoom(String roomname, Map properties)
			throws ChatRoomCreateException {
		throw new ChatRoomCreateException(roomname,
				Messages.IRCRootContainer_Exception_Create_Not_Supported, null);
	}

	protected IHistoryManager chatRoomHistoryManager = new IHistoryManager() {

		public IHistory getHistory(ID chatRoomID, Map options) {
			// TODO Auto-generated method stub
			return null;
		}

		public boolean isActive() {
			// TODO Auto-generated method stub
			return false;
		}

		public void setActive(boolean active) {

		}

		public Object getAdapter(Class adapter) {
			return null;
		}

	};

	public IHistoryManager getHistoryManager() {
		return chatRoomHistoryManager;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ecf.presence.chatroom.IChatRoomManager#getInvitationSender()
	 */
	public IChatRoomInvitationSender getInvitationSender() {
		return this;
	}

	public void sendInvitation(ID room, ID targetUser, String subject,
			String body) throws ECFException {
		if (connection == null)
			throw new ECFException(
					Messages.IRCRootContainer_EXCEPTION_CONNECTION_CANNOT_BE_NULL);
		connection.doInvite(targetUser.getName(), room.getName());
	}

	public void sendChatMessage(ID toID, ID threadID, Type type,
			String subject, String body, Map properties) throws ECFException {
		sendChatMessage(toID, body);
	}

	public void sendChatMessage(ID toID, String body) throws ECFException {
		if (toID == null) {
			throw new ECFException(
					Messages.IRCRootContainer_EXCEPTION_TARGETID_CANNOT_BE_NULL);
		}

		// FIXME: temporary workaround to allow for the sending of messages to
		// users that are operators
		String name = toID.getName();
		if (name.charAt(0) == '@') {
			name = name.substring(1);
		}
		connection.doPrivmsg(name, body);
	}

	public IChatMessageSender getPrivateMessageSender() {
		return this;
	}

	public ID[] getChatRoomParticipants() {
		// root channel has no participants
		return new ID[0];
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * org.eclipse.ecf.presence.chatroom.IChatRoomContainer#getChatRoomAdminSender
	 * ()
	 */
	public IChatRoomAdminSender getChatRoomAdminSender() {
		return null;
	}

}
