/*******************************************************************************
 * Copyright (c) 2004, 2007 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 192762, 197329, 190851
 *    Abner Ballardo <modlost@modlost.net> - bug 192756, 199336, 200630
 *    Jakub Jurkiewicz <jakub.jurkiewicz@pl.ibm.com> - bug 197332
 ******************************************************************************/
package org.eclipse.ecf.presence.ui.chatroom;

import java.net.URI;
import java.net.URISyntaxException;
import java.text.SimpleDateFormat;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.Assert;
import org.eclipse.ecf.core.IContainerListener;
import org.eclipse.ecf.core.events.*;
import org.eclipse.ecf.core.identity.*;
import org.eclipse.ecf.core.security.ConnectContextFactory;
import org.eclipse.ecf.core.user.IUser;
import org.eclipse.ecf.core.util.ECFException;
import org.eclipse.ecf.internal.presence.ui.*;
import org.eclipse.ecf.internal.presence.ui.preferences.PreferenceConstants;
import org.eclipse.ecf.presence.*;
import org.eclipse.ecf.presence.chatroom.*;
import org.eclipse.ecf.presence.im.IChatID;
import org.eclipse.ecf.presence.im.IChatMessage;
import org.eclipse.ecf.presence.ui.MessagesView;
import org.eclipse.jface.action.*;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.*;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.*;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.*;
import org.eclipse.swt.events.*;
import org.eclipse.swt.graphics.*;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.*;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.IWorkbenchSiteProgressService;

public class ChatRoomManagerView extends ViewPart implements IChatRoomInvitationListener {

	private static final String ATSIGN = "@"; //$NON-NLS-1$

	public static final String VIEW_ID = "org.eclipse.ecf.presence.ui.chatroom.ChatRoomManagerView"; //$NON-NLS-1$

	public static final String PARTICIPANTS_MENU_ID = "org.eclipse.ecf.presence.ui.chatroom.participantsView"; //$NON-NLS-1$ 

	private static final int RATIO_WRITE_PANE = 1;

	private static final int RATIO_READ_PANE = 9;

	private static final int RATIO_READ_WRITE_PANE = 85;

	private static final int RATIO_PRESENCE_PANE = 15;

	protected static final int DEFAULT_INPUT_HEIGHT = 25;

	protected static final int DEFAULT_INPUT_SEPARATOR = 5;

	private CTabFolder rootTabFolder = null;

	private ChatRoomTab rootChannelTab = null;

	private IChatRoomViewCloseListener rootCloseListener = null;

	private IChatRoomMessageSender rootMessageSender = null;

	/**
	 * UI independent renderer, that is aware of displaying any special fragments
	 * of message, like formatting, graphical attachments, emotional content, etc.
	 */
	private IMessageRenderer messageRenderer = null;

	Action outputClear = null;

	Action outputCopy = null;

	Action outputPaste = null;

	Action outputSelectAll = null;

	boolean rootDisposed = false;

	private boolean rootEnabled = false;

	private Hashtable chatRooms = new Hashtable();

	private IChatRoomCommandListener commandListener = null;

	private IChatRoomContainer container = null;

	private String localUserName = Messages.ChatRoomManagerView_DEFAULT_USER;

	private String hostName = Messages.ChatRoomManagerView_DEFAULT_HOST;

	class ChatRoomTab {
		private SashForm fullChat;

		private CTabItem tabItem;

		private SashForm rightSash;

		private StyledText subjectText;

		private StyledText outputText;

		private Text inputText;

		private Label participantsNumberLabel;

		private TableViewer participantsTable;

		private Action tabSelectAll;
		private Action tabCopy;
		private Action tabClear;
		private Action tabPaste;

		private boolean withParticipants;

		ChatRoomTab(CTabFolder parent, String name) {
			this(true, parent, name, null);
		}

		ChatRoomTab(boolean withParticipantsList, CTabFolder parent, String name, KeyListener keyListener) {
			withParticipants = withParticipantsList;
			tabItem = new CTabItem(parent, SWT.NULL);
			tabItem.setText(name);
			if (withParticipants) {
				fullChat = new SashForm(parent, SWT.HORIZONTAL);
				fullChat.setLayout(new FillLayout());

				Composite memberComp = new Composite(fullChat, SWT.NONE);
				GridLayout layout = new GridLayout(1, true);
				layout.marginWidth = 0;
				layout.marginHeight = 0;
				memberComp.setLayout(layout);

				participantsNumberLabel = new Label(memberComp, SWT.BORDER | SWT.READ_ONLY);
				participantsNumberLabel.setLayoutData(new GridData(SWT.FILL, SWT.BEGINNING, true, false));
				participantsNumberLabel.setAlignment(SWT.CENTER);
				participantsTable = new TableViewer(memberComp, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL | SWT.MULTI);
				participantsTable.setSorter(new ViewerSorter());
				participantsTable.getTable().setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
				participantsTable.addOpenListener(new IOpenListener() {
					public void open(OpenEvent event) {
						IStructuredSelection selection = (IStructuredSelection) event.getSelection();
						String user = ((ChatRoomParticipant) selection.getFirstElement()).getName();
						if (!ChatRoomManagerView.this.localUserName.equals(user)) {
							try {
								MessagesView messagesView = getMessagesView();
								messagesView.selectTab(container.getPrivateMessageSender(), null, createStringID(localUserName), createStringID(user));
								getSite().getPage().activate(messagesView);
							} catch (PartInitException e) {
								Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, NLS.bind(Messages.ChatRoomManagerView_EXCEPTION_MESSAGE_VIEW_INITIALIZATION, user), e));
							}
						}
					}
				});

				Composite rightComp = new Composite(fullChat, SWT.NONE);
				rightComp.setLayout(layout);

				subjectText = createStyledTextWidget(rightComp, SWT.SINGLE | SWT.BORDER);
				subjectText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
				/*
				 * The sendSubjectChange method in Smack 2.2.1 does not seem to be working correctly, so this whole block
				 * can be temporily removed.  See https://bugs.eclipse.org/bugs/show_bug.cgi?id=223560
				subjectText.addKeyListener(new KeyAdapter() {
					public void keyPressed(KeyEvent evt) {
						if (evt.character == SWT.CR || evt.character == SWT.KEYPAD_CR) {
							ChatRoom chatroom = (ChatRoom) chatRooms.get(tabItem.getText());
							if (chatroom != null) {
								IChatRoomAdminSender chatRoomAdminSender = chatroom.chatRoomContainer.getChatRoomAdminSender();
								try {
									if (chatRoomAdminSender != null) {
										chatRoomAdminSender.sendSubjectChange(subjectText.getText());
									}
								} catch (ECFException e) {
									Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, "sendSubjectChange", e));disconnected(); //$NON-NLS-1$
								}
							}
						}
					}
				});
				*/
				subjectText.setEditable(false);
				subjectText.setEnabled(false);

				rightSash = new SashForm(rightComp, SWT.VERTICAL);
				rightSash.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
			} else
				rightSash = new SashForm(parent, SWT.VERTICAL);

			outputText = createStyledTextWidget(rightSash, SWT.BORDER | SWT.WRAP | SWT.V_SCROLL | SWT.MULTI | SWT.READ_ONLY);
			outputText.setEditable(false);
			outputText.setLayoutData(new GridData(GridData.FILL_BOTH));

			inputText = new Text(rightSash, SWT.BORDER | SWT.MULTI | SWT.WRAP | SWT.V_SCROLL);
			if (keyListener != null)
				inputText.addKeyListener(keyListener);
			rightSash.setWeights(new int[] {RATIO_READ_PANE, RATIO_WRITE_PANE});
			if (withParticipants) {
				fullChat.setWeights(new int[] {RATIO_PRESENCE_PANE, RATIO_READ_WRITE_PANE});
				tabItem.setControl(fullChat);
			} else
				tabItem.setControl(rightSash);

			parent.setSelection(tabItem);

			makeActions();
			hookContextMenu();
			if (withParticipants) {
				hookParticipantsContextMenu();
			}

			StyledText st = getOutputText();
			if (st != null) {
				ScrollBar vsb = st.getVerticalBar();
				if (vsb != null) {
					vsb.addSelectionListener(scrollSelectionListener);
					vsb.addDisposeListener(new DisposeListener() {
						public void widgetDisposed(DisposeEvent e) {
							StyledText ot = getOutputText();
							if (ot != null) {
								ScrollBar sb = ot.getVerticalBar();
								if (sb != null)
									sb.removeSelectionListener(scrollSelectionListener);
							}
						}
					});
				}
			}

		}

		private SelectionListener scrollSelectionListener = new SelectionListener() {

			public void widgetDefaultSelected(SelectionEvent e) {
				// do nothing
			}

			public void widgetSelected(SelectionEvent e) {
				if (!isLastOutputInvisible(getOutputText())) {
					makeTabItemNormal();
				}
			}

		};

		protected void makeTabItemBold() {
			changeTabItem(true);
		}

		protected void makeTabItemNormal() {
			changeTabItem(false);
		}

		protected void changeTabItem(boolean bold) {
			CTabItem item = tabItem;
			Font oldFont = item.getFont();
			FontData[] fd = oldFont.getFontData();
			item.setFont(new Font(oldFont.getDevice(), fd[0].getName(), fd[0].getHeight(), (bold) ? SWT.BOLD : SWT.NORMAL));
		}

		private StyledText createStyledTextWidget(Composite parent, int styles) {
			SourceViewer result = null;
			try {
				result = new SourceViewer(parent, null, null, true, styles);
			} catch (NoClassDefFoundError e) {
				Activator.getDefault().getLog().log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, IStatus.WARNING, Messages.ChatRoomManagerView_WARNING_HYPERLINKING_NOT_AVAILABLE, e));
				return new StyledText(parent, styles);
			}
			result.configure(new ChatRoomViewerConfiguration(EditorsUI.getPreferenceStore(), container, ChatRoomManagerView.this));
			result.setDocument(new Document());
			return result.getTextWidget();
		}

		protected void outputClear() {
			if (MessageDialog.openConfirm(null, Messages.ChatRoomManagerView_CONFIRM_CLEAR_TEXT_OUTPUT_TITLE, Messages.ChatRoomManagerView_CONFIRM_CLEAR_TEXT_OUTPUT_MESSAGE)) {
				outputText.setText(""); //$NON-NLS-1$
			}
		}

		protected void outputCopy() {
			String t = outputText.getSelectionText();
			if (t == null || t.length() == 0) {
				outputText.selectAll();
			}
			outputText.copy();
			outputText.setSelection(outputText.getText().length());
		}

		private void fillContextMenu(IMenuManager manager) {
			manager.add(tabCopy);
			manager.add(tabPaste);
			manager.add(tabClear);
			manager.add(new Separator());
			manager.add(tabSelectAll);
			manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
		}

		private void hookContextMenu() {
			MenuManager menuMgr = new MenuManager();
			menuMgr.setRemoveAllWhenShown(true);
			menuMgr.addMenuListener(new IMenuListener() {
				public void menuAboutToShow(IMenuManager manager) {
					fillContextMenu(manager);
				}
			});
			Menu menu = menuMgr.createContextMenu(outputText);
			outputText.setMenu(menu);
			ISelectionProvider selectionProvider = new ISelectionProvider() {

				public void addSelectionChangedListener(ISelectionChangedListener listener) {
					// do nothing
				}

				public ISelection getSelection() {
					ISelection selection = new TextSelection(outputText.getSelectionRange().x, outputText.getSelectionRange().y);

					return selection;
				}

				public void removeSelectionChangedListener(ISelectionChangedListener listener) {
					// do nothing
				}

				public void setSelection(ISelection selection) {
					if (selection instanceof ITextSelection) {
						ITextSelection textSelection = (ITextSelection) selection;
						outputText.setSelection(textSelection.getOffset(), textSelection.getOffset() + textSelection.getLength());
					}
				}

			};
			getSite().registerContextMenu(menuMgr, selectionProvider);
		}

		private void hookParticipantsContextMenu() {
			MenuManager menuMgr = new MenuManager();
			menuMgr.addMenuListener(new IMenuListener() {
				public void menuAboutToShow(IMenuManager manager) {
					manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
				}
			});
			menuMgr.setRemoveAllWhenShown(true);
			Control control = participantsTable.getControl();
			Menu menu = menuMgr.createContextMenu(control);
			control.setMenu(menu);
			getSite().registerContextMenu(PARTICIPANTS_MENU_ID, menuMgr, participantsTable);
		}

		private void makeActions() {
			tabSelectAll = new Action() {
				public void run() {
					outputText.selectAll();
				}
			};
			tabSelectAll.setText(Messages.ChatRoomManagerView_SELECT_ALL_TEXT);
			tabSelectAll.setToolTipText(Messages.ChatRoomManagerView_SELECT_ALL_TOOLTIP);
			tabSelectAll.setAccelerator(SWT.CTRL | 'A');
			tabCopy = new Action() {
				public void run() {
					outputCopy();
				}
			};
			tabCopy.setText(Messages.ChatRoomManagerView_COPY_TEXT);
			tabCopy.setToolTipText(Messages.ChatRoomManagerView_COPY_TOOLTIP);
			tabCopy.setAccelerator(SWT.CTRL | 'C');
			tabCopy.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
			tabClear = new Action() {
				public void run() {
					outputClear();
				}
			};
			tabClear.setText(Messages.ChatRoomManagerView_CLEAR_TEXT);
			tabClear.setToolTipText(Messages.ChatRoomManagerView_CLEAR_TOOLTIP);
			tabPaste = new Action() {
				public void run() {
					getInputText().paste();
				}
			};
			tabPaste.setText(Messages.ChatRoomManagerView_PASTE_TEXT);
			tabPaste.setToolTipText(Messages.ChatRoomManagerView_PASTE_TOOLTIP);
			tabPaste.setAccelerator(SWT.CTRL | 'V');
			tabPaste.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_PASTE));

		}

		protected Text getInputText() {
			return inputText;
		}

		protected void setKeyListener(KeyListener listener) {
			if (listener != null)
				inputText.addKeyListener(listener);
		}

		protected Label getParticipantsLabel() {
			return participantsNumberLabel;
		}

		protected TableViewer getParticipantsViewer() {
			return participantsTable;
		}

		/**
		 * @return the <tt>StyledText</tt> widget that is displaying the output of the chatroom
		 */
		public StyledText getOutputText() {
			return outputText;
		}

		public void setSubject(String subject) {
			subjectText.setText(subject);
		}
	}

	public void createPartControl(Composite parent) {
		Composite rootComposite = new Composite(parent, SWT.NONE);
		rootComposite.setLayout(new FillLayout());
		boolean useTraditionalTabFolder = PlatformUI.getPreferenceStore().getBoolean(IWorkbenchPreferenceConstants.SHOW_TRADITIONAL_STYLE_TABS);
		rootTabFolder = new CTabFolder(rootComposite, SWT.NORMAL | SWT.CLOSE);
		rootTabFolder.setUnselectedCloseVisible(false);
		rootTabFolder.setSimple(useTraditionalTabFolder);
		PlatformUI.getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent event) {
				if (event.getProperty().equals(IWorkbenchPreferenceConstants.SHOW_TRADITIONAL_STYLE_TABS) && !rootTabFolder.isDisposed()) {
					rootTabFolder.setSimple(((Boolean) event.getNewValue()).booleanValue());
					rootTabFolder.redraw();
				}
			}
		});

		rootTabFolder.addCTabFolder2Listener(new CTabFolder2Adapter() {
			public void close(CTabFolderEvent event) {
				event.doit = closeTabItem((CTabItem) event.item);
			}
		});
	}

	private boolean closeTabItem(CTabItem tabItem) {
		ChatRoom chatRoom = findChatRoomForTabItem(tabItem);
		if (chatRoom == null) {
			return true;
		}
		if (MessageDialog.openQuestion(getSite().getShell(), Messages.ChatRoomManagerView_CLOSE_CHAT_ROOM_TITLE, NLS.bind(Messages.ChatRoomManagerView_CLOSE_CHAT_ROOM_MESSAGE, tabItem.getText()))) {
			chatRoom.chatRoomDisconnect();
			return true;
		}
		return false;
	}

	public IChatRoomContainer getRootChatRoomContainer() {
		return container;
	}

	/**
	 * @return chat room container of currently selected tab or null if none found.
	 */
	public IChatRoomContainer getActiveChatRoomContainer() {
		CTabItem selection = rootTabFolder.getSelection();
		if (selection != null) {
			ChatRoom chatRoom = findChatRoomForTabItem(selection);
			if (chatRoom != null) {
				return chatRoom.chatRoomContainer;
			}
		}

		return null;
	}

	private ChatRoom findChatRoomForTabItem(CTabItem tabItem) {
		for (Iterator i = chatRooms.values().iterator(); i.hasNext();) {
			ChatRoom cr = (ChatRoom) i.next();
			if (tabItem == cr.chatRoomTab.tabItem)
				return cr;
		}
		return null;
	}

	private Text getRootTextInput() {
		if (rootChannelTab == null)
			return null;
		return rootChannelTab.getInputText();
	}

	private StyledText getRootTextOutput() {
		if (rootChannelTab == null)
			return null;
		return rootChannelTab.getOutputText();
	}

	public void initializeWithoutManager(String username, String hostname, final IChatRoomCommandListener commandListener1, final IChatRoomViewCloseListener closeListener) {
		initializeWithManager(username, hostname, null, commandListener1, closeListener);
	}

	public void initializeWithManager(String localUserName1, String hostName1, final IChatRoomContainer rootChatRoomContainer, final IChatRoomCommandListener commandListener1, final IChatRoomViewCloseListener closeListener) {
		ChatRoomManagerView.this.localUserName = (localUserName1 == null) ? Messages.ChatRoomManagerView_DEFAULT_USER : localUserName1;
		ChatRoomManagerView.this.hostName = (hostName1 == null) ? Messages.ChatRoomManagerView_DEFAULT_HOST : hostName1;
		ChatRoomManagerView.this.rootCloseListener = closeListener;
		ChatRoomManagerView.this.commandListener = commandListener1;
		String viewTitle = localUserName1 + ATSIGN + hostName1;
		ChatRoomManagerView.this.setPartName(NLS.bind(Messages.ChatRoomManagerView_VIEW_TITLE, viewTitle));
		ChatRoomManagerView.this.setTitleToolTip(Messages.ChatRoomManagerView_VIEW_TITLE_HOST_PREFIX + ChatRoomManagerView.this.hostName);
		if (rootChatRoomContainer != null) {
			ChatRoomManagerView.this.container = rootChatRoomContainer;
			ChatRoomManagerView.this.rootMessageSender = rootChatRoomContainer.getChatRoomMessageSender();
			rootChannelTab = new ChatRoomTab(false, rootTabFolder, ChatRoomManagerView.this.hostName, new KeyListener() {
				public void keyPressed(KeyEvent evt) {
					handleKeyPressed(evt);
				}

				public void keyReleased(KeyEvent evt) {
					// do nothing
				}
			});
			makeActions();
			hookContextMenu();
			if (rootChatRoomContainer.getConnectedID() == null) {
				StyledText outputText = getRootTextOutput();
				if (!outputText.isDisposed())
					outputText.setText(new SimpleDateFormat(Messages.ChatRoomManagerView_CONNECT_DATE_TIME_FORMAT).format(new Date()) + NLS.bind(Messages.ChatRoomManagerView_CONNECT_MESSAGE, viewTitle));
			}
		}
		setEnabled(false);
	}

	public void setEnabled(boolean enabled) {
		this.rootEnabled = enabled;
		Text inputText = getRootTextInput();
		if (inputText != null && !inputText.isDisposed())
			inputText.setEnabled(enabled);
	}

	public boolean isEnabled() {
		return rootEnabled;
	}

	protected void clearInput() {
		Text textInput = getRootTextInput();
		if (textInput != null)
			textInput.setText(""); //$NON-NLS-1$
	}

	public void sendMessageLine(String line) {
		try {
			if (rootMessageSender != null)
				rootMessageSender.sendMessage(line);
		} catch (ECFException e) {
			// And cut ourselves off
			removeLocalUser();
		}
	}

	public void disconnected() {
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				if (rootDisposed)
					return;
				setEnabled(false);
				setPartName(NLS.bind(Messages.ChatRoomManagerView_VIEW_DISABLED_NAME, getPartName()));
			}
		});
	}

	protected CTabItem getTabItem(String targetName) {
		CTabItem[] items = rootTabFolder.getItems();
		for (int i = 0; i < items.length; i++) {
			if (items[i].getText().equals(targetName)) {
				return items[i];
			}
		}
		return null;
	}

	protected void doJoinRoom(final IChatRoomInfo roomInfo, final String password) {
		final ID targetRoomID = roomInfo.getRoomID();
		final String targetRoomName = targetRoomID.getName();
		// first, check to see if we already have it open. If so just activate
		ChatRoom room = (ChatRoom) chatRooms.get(targetRoomName);

		if (room != null && room.isConnected()) {
			room.setSelected();
			return;
		}

		// Then we create a new chatRoomContainer from the roomInfo
		try {
			final IChatRoomContainer chatRoomContainer = roomInfo.createChatRoomContainer();

			// Setup new user interface (new tab)
			final ChatRoom chatroom = new ChatRoom(chatRoomContainer, new ChatRoomTab(rootTabFolder, targetRoomName));
			// setup message listener
			chatRoomContainer.addMessageListener(new IIMMessageListener() {
				public void handleMessageEvent(IIMMessageEvent messageEvent) {
					if (messageEvent instanceof IChatRoomMessageEvent) {
						IChatRoomMessage m = ((IChatRoomMessageEvent) messageEvent).getChatRoomMessage();
						chatroom.handleMessage(m.getFromID(), m.getMessage());
					}
				}
			});
			// setup participant listener
			chatRoomContainer.addChatRoomParticipantListener(new IChatRoomParticipantListener() {
				public void handlePresenceUpdated(ID fromID, IPresence presence) {
					chatroom.handlePresence(fromID, presence);
				}

				public void handleArrived(IUser participant) {
					// do nothing
				}

				public void handleUpdated(IUser updatedParticipant) {
					// do nothing
				}

				public void handleDeparted(IUser participant) {
					// do nothing
				}
			});
			chatRoomContainer.addListener(new IContainerListener() {
				public void handleEvent(IContainerEvent evt) {
					if (evt instanceof IContainerDisconnectedEvent || evt instanceof IContainerEjectedEvent) {
						chatroom.disconnected();
					}
				}
			});
			// Now connect/join
			Display.getDefault().asyncExec(new Runnable() {
				public void run() {
					try {
						chatRoomContainer.connect(targetRoomID, ConnectContextFactory.createPasswordConnectContext(password));
						chatRooms.put(targetRoomName, chatroom);
					} catch (Exception e) {
						MessageDialog.openError(getSite().getShell(), "Connect Error", //$NON-NLS-1$
								NLS.bind("Could not connect to {0}.\n\nError is {1}.", //$NON-NLS-1$
										targetRoomName, e.getLocalizedMessage()));
					}
				}
			});
		} catch (Exception e) {
			MessageDialog.openError(getSite().getShell(), "Container Create Error", //$NON-NLS-1$
					NLS.bind("Could not create chatRoomContainer for {0}.\n\nError is {1}.", //$NON-NLS-1$
							targetRoomName, e.getLocalizedMessage()));
		}
	}

	class ChatRoom implements IChatRoomInvitationListener, KeyListener {

		private IChatRoomContainer chatRoomContainer;

		private ChatRoomTab chatRoomTab;

		private IChatRoomMessageSender chatRoomMessageSender;

		private IUser localUser;

		private Label chatRoomParticipantsLabel;

		private TableViewer chatRoomParticipantViewer = null;

		/**
		 * A list of available nicknames for nickname completion via the 'tab'
		 * key.
		 */
		private ArrayList options;

		/**
		 * Denotes the number of options that should be available for the user
		 * to cycle through when pressing the 'tab' key to perform nickname
		 * completion. The default value is set to 5.
		 */
		private int maximumCyclingOptions = 5;

		/**
		 * The length of a nickname's prefix that has already been typed in by
		 * the user. This is used to remove the beginning part of the available
		 * nickname choices.
		 */
		private int prefixLength;

		/**
		 * The index of the next nickname to select from {@link #options}.
		 */
		private int choice = 0;

		/**
		 * The length of the user's nickname that remains resulting from
		 * subtracting the nickname's length from the prefix that the user has
		 * keyed in already.
		 */
		private int nickRemainder;

		/**
		 * The caret position when the user first started
		 * cycling through nickname completion options.
		 */
		private int caret;

		/**
		 * The character to enter after the user's nickname has been
		 * autocompleted. The default value is a colon (':').
		 */
		private char nickCompletionSuffix = ':';

		/**
		 * Indicates whether the user is currently cycling over the list of
		 * nicknames for nickname completion.
		 */
		private boolean isCycling = false;

		/**
		 * Check to see whether the user is currently starting the line of text
		 * with a nickname at the beginning of the message. This determines
		 * whether {@link #nickCompletionSuffix} should be inserted when
		 * performing autocompletion. If the user is not at the beginning of the
		 * message, it is likely that the user is typing another user's name to
		 * reference that person and not to direct the message to said person,
		 * as such, the <code>nickCompletionSuffix</code> does not need to be
		 * appended.
		 */
		private boolean isAtStart = false;

		private CTabItem itemSelected = null;

		private Text getInputText() {
			return chatRoomTab.getInputText();
		}

		private StyledText getOutputText() {
			return chatRoomTab.getOutputText();
		}

		ChatRoom(IChatRoomContainer container, ChatRoomTab tabItem) {
			Assert.isNotNull(container);
			Assert.isNotNull(tabItem);
			this.chatRoomContainer = container;
			this.chatRoomMessageSender = container.getChatRoomMessageSender();
			this.chatRoomTab = tabItem;
			options = new ArrayList();
			this.chatRoomTab.setKeyListener(this);
			this.chatRoomParticipantsLabel = tabItem.getParticipantsLabel();
			this.chatRoomParticipantViewer = tabItem.getParticipantsViewer();

			chatRoomContainer.addChatRoomAdminListener(new IChatRoomAdminListener() {
				public void handleSubjectChange(ID from, final String newSubject) {
					if (!chatRoomTab.getInputText().isDisposed()) {
						chatRoomTab.getInputText().getDisplay().asyncExec(new Runnable() {
							public void run() {
								chatRoomTab.setSubject(newSubject);
							}
						});
					}
				}
			});

			rootTabFolder.setUnselectedCloseVisible(true);

			rootTabFolder.addSelectionListener(new SelectionListener() {

				public void widgetDefaultSelected(SelectionEvent e) {
					// do nothing
				}

				public void widgetSelected(SelectionEvent e) {
					itemSelected = (CTabItem) e.item;
					if (itemSelected == chatRoomTab.tabItem)
						makeTabItemNormal();
					if (rootChannelTab != null && itemSelected == rootChannelTab.tabItem)
						rootChannelTab.makeTabItemNormal();
				}
			});

			StyledText st = getOutputText();
			if (st != null) {
				ScrollBar vsb = st.getVerticalBar();
				if (vsb != null) {
					vsb.addSelectionListener(scrollSelectionListener);
					vsb.addDisposeListener(new DisposeListener() {
						public void widgetDisposed(DisposeEvent e) {
							StyledText ot = getOutputText();
							if (ot != null) {
								ScrollBar vb = ot.getVerticalBar();
								if (vb != null)
									vb.removeSelectionListener(scrollSelectionListener);
							}
						}
					});
				}
			}
		}

		private SelectionListener scrollSelectionListener = new SelectionListener() {

			public void widgetDefaultSelected(SelectionEvent e) {
				// do nothing
			}

			public void widgetSelected(SelectionEvent e) {
				if (!isLastOutputInvisible(getOutputText())) {
					makeTabItemNormal();
				}
			}

		};

		protected void makeTabItemBold() {
			changeTabItem(true);
		}

		protected void makeTabItemNormal() {
			changeTabItem(false);
		}

		protected void changeTabItem(boolean bold) {
			CTabItem item = chatRoomTab.tabItem;
			Font oldFont = item.getFont();
			FontData[] fd = oldFont.getFontData();
			item.setFont(new Font(oldFont.getDevice(), fd[0].getName(), fd[0].getHeight(), (bold) ? SWT.BOLD : SWT.NORMAL));
		}

		public void handleMessage(final ID fromID, final String messageBody) {
			Display.getDefault().asyncExec(new Runnable() {
				public void run() {
					if (rootDisposed)
						return;
					appendText(chatRoomTab, getOutputText(), new ChatLine(messageBody, new ChatRoomParticipant(fromID)));
				}
			});
		}

		public void handleInvitationReceived(ID roomID, ID from, String subject, String body) {
			// XXX TODO show UI for invitation
		}

		public void keyPressed(KeyEvent e) {
			handleKeyPressed(e);
		}

		public void keyReleased(KeyEvent e) {
			handleKeyReleased(e);
		}

		protected void handleKeyPressed(KeyEvent evt) {
			Text inputText = getInputText();
			if (evt.character == SWT.CR) {
				if (inputText.getText().trim().length() > 0)
					handleTextInput(inputText.getText());
				clearInput();
				makeTabItemNormal();
				if (Activator.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.PREFERENCES_SCROLLONINPUT))
					scrollToEnd(getOutputText());
				evt.doit = false;
				isCycling = false;
			} else if (evt.character == SWT.TAB) {
				// don't propogate the event upwards and insert a tab character
				evt.doit = false;
				int pos = inputText.getCaretPosition();
				// if the user is at the beginning of the line, do nothing
				if (pos == 0)
					return;
				String text = inputText.getText();
				// check to see if the user is currently cycling through the
				// available nicknames
				if (isCycling) {
					// if everything's been cycled over, start over at zero
					if (choice == options.size()) {
						choice = 0;
					}

					String append = ((String) options.get(choice++)) + (isAtStart ? nickCompletionSuffix + " " : " "); //$NON-NLS-1$ //$NON-NLS-2$
					// remove the previous completion proposal and insert the new one
					inputText.setText(text.substring(0, caret - prefixLength) + append + text.substring(caret + nickRemainder));
					// subtract the prefix so we remember where we were originally
					nickRemainder = append.length() - prefixLength;
					// set the caret position to be the place where the nickname
					// completion ended
					inputText.setSelection(caret + nickRemainder);
				} else {
					// the user is not cycling, so we need to identify what the
					// user has typed based on the current caret position
					int count = pos - 1;
					// keep looping until the whitespace has been identified or
					// the beginning of the message has been reached
					while (count > -1 && !Character.isWhitespace(text.charAt(count))) {
						count--;
					}
					count++;
					// remove all previous options
					options.clear();
					// get the prefix that the user typed as a lowercase string
					String prefix = text.substring(count, pos).toLowerCase();
					isAtStart = count == 0;
					// if what's found was actually whitespace, do nothing
					if (prefix.trim().equals("")) { //$NON-NLS-1$
						return;
					}
					// get all of the users in this room and store them if they
					// start with the prefix that the user has typed
					TableItem[] participants = chatRoomParticipantViewer.getTable().getItems();
					for (int i = 0; i < participants.length; i++) {
						String name = participants[i].getText();
						// do a lowercase comparison because we should display options that differ in casing
						if (name.toLowerCase().startsWith(prefix)) {
							options.add(name);
						}
					}

					// simply return if no matches have been found
					if (options.isEmpty())
						return;

					prefixLength = prefix.length();
					if (options.size() == 1) {
						String nickname = (String) options.get(0);
						// since only one nickname is available, we'll select
						// the prefix that has been entered and then replace it
						// with the nickname option
						inputText.setSelection(pos - prefixLength, pos);
						inputText.insert(nickname + (isAtStart ? nickCompletionSuffix + " " : " ")); //$NON-NLS-1$ //$NON-NLS-2$
					} else if (options.size() <= maximumCyclingOptions) {
						// note that the user is currently cycling through
						// options and also store the current caret position
						isCycling = true;
						caret = pos;
						choice = 0;
						// insert the nickname after removing the prefix
						String nickname = options.get(choice++) + (isAtStart ? nickCompletionSuffix + " " : " "); //$NON-NLS-1$ //$NON-NLS-2$
						// select the prefix of the proposal
						inputText.setSelection(pos - prefixLength, pos);
						// and then replace it with a proposal
						inputText.insert(nickname);
						// store the length of this truncated nickname so that
						// it can be removed when the user is cycling
						nickRemainder = nickname.length() - prefixLength;
					} else {
						// as there are too many choices for the user to pick
						// from, simply display all of the available ones on the
						// chat window so that the user can get a visual
						// indicator of what's available and narrow down the
						// choices by typing a few more additional characters
						StringBuffer choices = new StringBuffer();
						synchronized (choices) {
							for (int i = 0; i < options.size(); i++) {
								choices.append(options.get(i)).append(' ');
							}
							choices.delete(choices.length() - 1, choices.length());
						}
						appendText(chatRoomTab, getOutputText(), new ChatLine(choices.toString()));
					}
				}
			} else {
				// remove the cycling marking for any other key pressed
				isCycling = false;
			}
		}

		protected void handleKeyReleased(KeyEvent evt) {
			if (evt.character == SWT.TAB) {
				// don't move to the next widget or try to add tabs
				evt.doit = false;
			}
		}

		protected void handleTextInput(String text) {
			if (chatRoomMessageSender == null) {
				MessageDialog.openError(getViewSite().getShell(), Messages.ChatRoomManagerView_NOT_CONNECTED_TITLE, Messages.ChatRoomManagerView_NOT_CONNECTED_MESSAGE);
				return;
			}
			String output = processForCommand(chatRoomContainer, text);
			if (output != null)
				sendMessageLine(output);
		}

		protected void chatRoomDisconnect() {
			if (chatRoomContainer != null)
				chatRoomContainer.disconnect();
		}

		protected void clearInput() {
			getInputText().setText(""); //$NON-NLS-1$
		}

		protected void sendMessageLine(String line) {
			try {
				chatRoomMessageSender.sendMessage(line);
			} catch (ECFException e) {
				disconnected();
			}
		}

		public void handlePresence(final ID fromID, final IPresence presence) {
			Display.getDefault().asyncExec(new Runnable() {
				public void run() {
					if (rootDisposed)
						return;
					boolean isAdd = presence.getType().equals(IPresence.Type.AVAILABLE);
					ChatRoomParticipant p = new ChatRoomParticipant(fromID);
					if (isAdd) {
						if (localUser == null)
							localUser = p;
						addParticipant(p);
					} else
						removeParticipant(p);
				}
			});
		}

		public void disconnected() {
			Display.getDefault().asyncExec(new Runnable() {
				public void run() {
					if (rootDisposed)
						return;
					Text inputText = getInputText();
					if (!inputText.isDisposed())
						inputText.setEnabled(false);
				}
			});
		}

		protected boolean isConnected() {
			Text inputText = getInputText();
			return !inputText.isDisposed() && inputText.isEnabled();
		}

		protected void setSelected() {
			rootTabFolder.setSelection(chatRoomTab.tabItem);
		}

		protected void addParticipant(IUser p) {
			if (p != null) {
				ID id = p.getID();
				if (id != null) {
					Preferences prefs = Activator.getDefault().getPluginPreferences();

					if (prefs.getBoolean(PreferenceConstants.CHATROOM_SHOW_USER_PRESENCE))
						appendText(chatRoomTab, getOutputText(), new ChatLine(NLS.bind(Messages.ChatRoomManagerView_ENTERED_MESSAGE, getUsernameFromID(id)), null));
					chatRoomParticipantViewer.add(p);
					chatRoomParticipantsLabel.setText(NLS.bind(Messages.ChatRoomManagerView_USERS_IN_CHAT_ROOM, String.valueOf(chatRoomContainer.getChatRoomParticipants().length)));
				}
			}
		}

		protected boolean isLocalUser(ID id) {
			if (localUser == null)
				return false;
			else if (localUser.getID().equals(id))
				return true;
			else
				return false;
		}

		protected void removeLocalUser() {
			// It's us that's gone away... so we're outta here
			String title = getPartName();
			setPartName(NLS.bind(Messages.ChatRoomManagerView_VIEW_DISABLED_NAME, title));
			removeAllParticipants();
			disconnect();
			setEnabled(false);
		}

		protected void removeParticipant(IUser p) {
			if (p != null) {
				ID id = p.getID();
				if (id != null) {
					Preferences prefs = Activator.getDefault().getPluginPreferences();

					if (prefs.getBoolean(PreferenceConstants.CHATROOM_SHOW_USER_PRESENCE))
						appendText(chatRoomTab, getOutputText(), new ChatLine(NLS.bind(Messages.ChatRoomManagerView_LEFT_MESSAGE, getUsernameFromID(id)), null));
					chatRoomParticipantViewer.remove(p);
					chatRoomParticipantsLabel.setText(NLS.bind(Messages.ChatRoomManagerView_USERS_IN_CHAT_ROOM, String.valueOf(chatRoomContainer.getChatRoomParticipants().length)));
				}
			}
		}

		protected void removeAllParticipants() {
			Table t = chatRoomParticipantViewer.getTable();
			for (int i = 0; i < t.getItemCount(); i++) {
				Object o = chatRoomParticipantViewer.getElementAt(i);
				if (o != null)
					chatRoomParticipantViewer.remove(o);
			}
			chatRoomParticipantsLabel.setText(NLS.bind(Messages.ChatRoomManagerView_USERS_IN_CHAT_ROOM, String.valueOf(chatRoomContainer.getChatRoomParticipants().length)));
		}
	}

	protected void handleTextInput(String text) {
		if (rootMessageSender == null) {
			MessageDialog.openError(getViewSite().getShell(), Messages.ChatRoomManagerView_NOT_CONNECTED_TITLE, Messages.ChatRoomManagerView_NOT_CONNECTED_MESSAGE);
		} else {
			String output = processForCommand(null, text);
			if (output != null)
				sendMessageLine(output);
		}
	}

	protected String processForCommand(IChatRoomContainer chatRoomContainer, String text) {
		IChatRoomCommandListener l = commandListener;
		if (l != null)
			return l.handleCommand(chatRoomContainer, text);
		return text;
	}

	protected void handleEnter() {
		Text inputText = getRootTextInput();
		if (inputText.getText().trim().length() > 0)
			handleTextInput(inputText.getText());
		clearInput();
		scrollToEnd(getRootTextOutput());
		if (rootChannelTab != null)
			rootChannelTab.makeTabItemNormal();
	}

	protected void handleKeyPressed(KeyEvent evt) {
		if (evt.character == SWT.CR) {
			handleEnter();
			evt.doit = false;
		}
	}

	public void setFocus() {
		Text text = getRootTextInput();
		if (text != null)
			text.setFocus();
	}

	public void joinRoom(final IChatRoomInfo info, final String password) {
		Display.getDefault().syncExec(new Runnable() {
			public void run() {
				if (rootDisposed)
					return;
				doJoinRoom(info, password);
			}
		});
	}

	public void dispose() {
		disconnect();
		rootDisposed = true;
		super.dispose();
	}

	protected String getMessageString(ID fromID, String text) {
		return NLS.bind(Messages.ChatRoomManagerView_MESSAGE, fromID.getName(), text);
	}

	private ID createStringID(String str) {
		try {
			return IDFactory.getDefault().createStringID(str);
		} catch (IDCreateException e) {
			// Should not happen
		}

		return null;
	}

	private MessagesView getMessagesView() throws PartInitException {
		IWorkbenchPage page = getSite().getPage();
		MessagesView messageView = (MessagesView) page.findView(MessagesView.VIEW_ID);
		if (messageView == null) {
			messageView = (MessagesView) page.showView(MessagesView.VIEW_ID, null, IWorkbenchPage.VIEW_CREATE);
		}

		return messageView;
	}

	/**
	 * A delegate method to handle chat messages.
	 * @param message the chat message that has been received
	 * @since 1.1
	 */
	public void handleChatMessage(final IChatMessage message) {
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				try {
					ID targetID = createStringID(localUserName);
					MessagesView messageView = getMessagesView();

					IWorkbenchSiteProgressService service = (IWorkbenchSiteProgressService) messageView.getSite().getAdapter(IWorkbenchSiteProgressService.class);

					if (container.getPrivateMessageSender() != null) {
						messageView.openTab(container.getPrivateMessageSender(), null, targetID, message.getFromID());

						messageView.showMessage(message);
						service.warnOfContentChange();
					}
				} catch (Exception e) {
					Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, IStatus.ERROR, Messages.ChatRoomManagerView_EXCEPTION_MESSAGE_VIEW_INITIALIZATION + message.getFromID(), e));
				}
			}
		});
	}

	public void handleMessage(final ID fromID, final String messageBody) {
		Display.getDefault().asyncExec(new Runnable() {
			public void run() {
				if (rootDisposed)
					return;
				if (rootChannelTab != null) {
					appendText(rootChannelTab, getRootTextOutput(), new ChatLine(messageBody, new ChatRoomParticipant(fromID)));
					rootChannelTab.makeTabItemBold();
				}
			}
		});
	}

	/**
	 * @return String username for given <code>targetID</code>
	 */
	public static String getUsernameFromID(ID targetID) {
		IChatID chatID = (IChatID) targetID.getAdapter(IChatID.class);
		if (chatID != null)
			return chatID.getUsername();
		try {
			URI uri = new URI(targetID.getName());
			String user = uri.getUserInfo();
			return user == null ? targetID.getName() : user;
		} catch (URISyntaxException e) {
			String userAtHost = targetID.getName();
			int atIndex = userAtHost.lastIndexOf(ATSIGN);
			if (atIndex != -1)
				userAtHost = userAtHost.substring(0, atIndex);
			return userAtHost;
		}
	}

	/**
	 * @return String hostname for given <code>targetID</code>
	 */
	public static String getHostnameFromID(ID targetID) {
		IChatID chatID = (IChatID) targetID.getAdapter(IChatID.class);
		if (chatID != null)
			return chatID.getHostname();
		try {
			URI uri = new URI(targetID.getName());
			String host = uri.getHost();
			return host == null ? targetID.getName() : host;
		} catch (URISyntaxException e) {
			String userAtHost = targetID.getName();
			int atIndex = userAtHost.lastIndexOf(ATSIGN);
			if (atIndex != -1)
				userAtHost = userAtHost.substring(atIndex + 1);
			return userAtHost;
		}
	}

	class ChatRoomParticipant implements IUser, IActionFilter {
		private static final long serialVersionUID = 2008114088656711572L;

		ID id;

		public ChatRoomParticipant(ID id) {
			this.id = id;
		}

		public ID getID() {
			return id;
		}

		public String getName() {
			return toString();
		}

		public boolean equals(Object other) {
			if (!(other instanceof ChatRoomParticipant))
				return false;
			ChatRoomParticipant o = (ChatRoomParticipant) other;
			if (id.equals(o.id))
				return true;
			return false;
		}

		public int hashCode() {
			return id.hashCode();
		}

		public String toString() {
			return getUsernameFromID(id);
		}

		public Map getProperties() {
			return null;
		}

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

		/*
		 * (non-Javadoc)
		 * 
		 * @see org.eclipse.ecf.core.user.IUser#getNickname()
		 */
		public String getNickname() {
			return getName();
		}

		public boolean testAttribute(Object target, String name, String value) {
			if (name.equals("scheme")) { //$NON-NLS-1$
				IChatRoomContainer c = ChatRoomManagerView.this.container;
				String scheme = c.getConnectedID().getNamespace().getScheme();
				return scheme.equalsIgnoreCase(value);
			}
			return false;
		}
	}

	public void disconnect() {
		if (rootCloseListener != null) {
			rootCloseListener.chatRoomViewClosing();
		}
		// disconnect from each chat room container
		for (Iterator i = chatRooms.values().iterator(); i.hasNext();) {
			ChatRoom chatRoom = (ChatRoom) i.next();
			IChatRoomContainer c = chatRoom.chatRoomContainer;
			if (c != null)
				c.disconnect();
		}
		rootMessageSender = null;
		rootCloseListener = null;
		chatRooms.clear();
	}

	protected void removeLocalUser() {
		// It's us that's gone away... so we're outta here
		String title = getPartName();
		setPartName(NLS.bind(Messages.ChatRoomManagerView_VIEW_DISABLED_NAME, title));
		disconnect();
		setEnabled(false);
	}

	public void handleInvitationReceived(ID roomID, ID from, String subject, String body) {
		// XXX TODO
	}

	private boolean isLastOutputInvisible(StyledText chatText) {
		Point locAtEnd = chatText.getLocationAtOffset(chatText.getText().length());
		Rectangle bounds = chatText.getBounds();
		return (locAtEnd.y > bounds.height + 5);
	}

	private void scrollToEnd(StyledText chatText) {
		chatText.setSelection(chatText.getText().length());
	}

	protected void appendText(ChatRoomTab chatRoomTab, StyledText st, ChatLine text) {
		if (st == null || text == null) {
			return;
		}

		boolean isAtEndBeforeAppend = !isLastOutputInvisible(st);

		String originator = null;
		if (text.getOriginator() != null) {
			originator = text.getOriginator().getNickname();
		}

		if (messageRenderer == null)
			messageRenderer = new MessageRenderer();

		String output = messageRenderer.render(text.getText(), originator, localUserName);
		StyleRange[] ranges = messageRenderer.getStyleRanges();

		if (output == null) {
			return;
		}

		int startRange = st.getText().length();

		if (!text.isNoCRLF()) {
			output += "\n"; //$NON-NLS-1$
		}

		st.append(output);

		if (ranges != null) {

			// set all ranges to start as message line starts
			for (int i = 0; i < ranges.length; i++) {
				ranges[i].start += startRange;
			}
			st.replaceStyleRanges(startRange, output.length(), ranges);
		}

		if (isAtEndBeforeAppend)
			scrollToEnd(st);

		if (isCurrentlyActive(chatRoomTab))
			chatRoomTab.makeTabItemNormal();
		else
			chatRoomTab.makeTabItemBold();
	}

	protected void outputClear() {
		if (MessageDialog.openConfirm(null, Messages.ChatRoomManagerView_CLEAR_CONFIRM_TITLE, Messages.ChatRoomManagerView_CLEAR_CONFIRM_MESSAGE)) {
			getRootTextOutput().setText(""); //$NON-NLS-1$
		}
	}

	protected void outputCopy() {
		StyledText outputText = getRootTextOutput();
		String t = outputText.getSelectionText();
		if (t == null || t.length() == 0) {
			outputText.selectAll();
		}
		outputText.copy();
		outputText.setSelection(outputText.getText().length());
	}

	protected void outputSelectAll() {
		getRootTextOutput().selectAll();
	}

	protected void makeActions() {

		outputSelectAll = new Action() {
			public void run() {
				outputSelectAll();
			}
		};
		outputSelectAll.setText(Messages.ChatRoomManagerView_SELECT_ALL_TEXT);
		outputSelectAll.setToolTipText(Messages.ChatRoomManagerView_SELECT_ALL_TOOLTIP);
		outputSelectAll.setAccelerator(SWT.CTRL | 'A');
		outputCopy = new Action() {
			public void run() {
				outputCopy();
			}
		};
		outputCopy.setText(Messages.ChatRoomManagerView_COPY_TEXT);
		outputCopy.setToolTipText(Messages.ChatRoomManagerView_COPY_TOOLTIP);
		outputCopy.setAccelerator(SWT.CTRL | 'C');
		outputCopy.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_COPY));
		outputClear = new Action() {
			public void run() {
				outputClear();
			}
		};
		outputClear.setText(Messages.ChatRoomManagerView_CLEAR_TEXT);
		outputClear.setToolTipText(Messages.ChatRoomManagerView_CLEAR_TOOLTIP);
		outputPaste = new Action() {
			public void run() {
				getRootTextInput().paste();
			}
		};
		outputPaste.setText(Messages.ChatRoomManagerView_PASTE_TEXT);
		outputPaste.setToolTipText(Messages.ChatRoomManagerView_PASTE_TOOLTIP);
		outputPaste.setAccelerator(SWT.CTRL | 'V');
		outputPaste.setImageDescriptor(PlatformUI.getWorkbench().getSharedImages().getImageDescriptor(ISharedImages.IMG_TOOL_PASTE));
	}

	private void fillContextMenu(IMenuManager manager) {
		manager.add(outputCopy);
		manager.add(outputPaste);
		manager.add(outputClear);
		manager.add(new Separator());
		manager.add(outputSelectAll);
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
	}

	private void hookContextMenu() {
		MenuManager menuMgr = new MenuManager();
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				fillContextMenu(manager);
			}
		});
		StyledText outputText = getRootTextOutput();
		Menu menu = menuMgr.createContextMenu(outputText);
		outputText.setMenu(menu);
		ISelectionProvider selectionProvider = new ISelectionProvider() {

			public void addSelectionChangedListener(ISelectionChangedListener listener) {
				// do nothing
			}

			public ISelection getSelection() {
				StyledText ot = getRootTextOutput();
				ISelection selection = new TextSelection(ot.getSelectionRange().x, ot.getSelectionRange().y);

				return selection;
			}

			public void removeSelectionChangedListener(ISelectionChangedListener listener) {
				// do nothing
			}

			public void setSelection(ISelection selection) {
				if (selection instanceof ITextSelection) {
					ITextSelection textSelection = (ITextSelection) selection;
					StyledText ot = getRootTextOutput();
					ot.setSelection(textSelection.getOffset(), textSelection.getOffset() + textSelection.getLength());
				}
			}

		};
		getSite().registerContextMenu(menuMgr, selectionProvider);
	}

	public void setMessageRenderer(IMessageRenderer defaultMessageRenderer) {
		this.messageRenderer = defaultMessageRenderer;
	}

	private boolean isCurrentlyActive(ChatRoomTab chatRoomTab) {
		int selected = rootTabFolder.getSelectionIndex();
		if (selected != -1) {
			CTabItem item = rootTabFolder.getItem(selected);
			if (item == chatRoomTab.tabItem)
				return true;
		}
		return false;
	}
}