/****************************************************************************
 * Copyright (c) 2007, 2009 Remy Suen, 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:
 *    Remy Suen <remy.suen@gmail.com> - initial API and implementation
 *    Hiroyuki Inaba <hiroyuki.inaba@gmail.com> - Bug 259856 The error message when the chat message cannot be sent is not correct.
 *****************************************************************************/
package org.eclipse.ecf.presence.ui;

import java.text.SimpleDateFormat;
import java.util.*;
import org.eclipse.core.runtime.*;
import org.eclipse.ecf.core.identity.ID;
import org.eclipse.ecf.core.util.ECFException;
import org.eclipse.ecf.internal.presence.ui.Activator;
import org.eclipse.ecf.internal.presence.ui.Messages;
import org.eclipse.ecf.presence.im.*;
import org.eclipse.jface.action.*;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.source.SourceViewer;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
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.FillLayout;
import org.eclipse.swt.widgets.*;
import org.eclipse.ui.IWorkbenchPreferenceConstants;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.editors.text.EditorsUI;
import org.eclipse.ui.editors.text.TextSourceViewerConfiguration;
import org.eclipse.ui.part.ViewPart;
import org.eclipse.ui.progress.UIJob;

public class MessagesView extends ViewPart {

	private static final SimpleDateFormat FORMATTER = new SimpleDateFormat("(hh:mm:ss a)"); //$NON-NLS-1$

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

	private static final int[] WEIGHTS = {75, 25};

	private CTabFolder tabFolder;

	private Color redColor;

	private Color blueColor;

	private Map tabs;

	private boolean showTimestamps = true;

	public MessagesView() {
		tabs = new HashMap();
	}

	public void createPartControl(Composite parent) {
		boolean useTraditionalTabFolder = PlatformUI.getPreferenceStore().getBoolean(IWorkbenchPreferenceConstants.SHOW_TRADITIONAL_STYLE_TABS);

		tabFolder = new CTabFolder(parent, SWT.CLOSE);
		tabFolder.setTabPosition(SWT.BOTTOM);
		tabFolder.setSimple(useTraditionalTabFolder);
		PlatformUI.getPreferenceStore().addPropertyChangeListener(new IPropertyChangeListener() {
			public void propertyChange(PropertyChangeEvent event) {
				if (event.getProperty().equals(IWorkbenchPreferenceConstants.SHOW_TRADITIONAL_STYLE_TABS) && !tabFolder.isDisposed()) {
					tabFolder.setSimple(((Boolean) event.getNewValue()).booleanValue());
					tabFolder.redraw();
				}
			}
		});

		tabFolder.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				Iterator it = tabs.values().iterator();
				while (it.hasNext()) {
					ChatTab tab = (ChatTab) it.next();
					if (tab.item == e.item) {
						tab.inputText.setFocus();
						break;
					}
				}
			}
		});

		tabFolder.addCTabFolder2Listener(new CTabFolder2Adapter() {
			public void close(CTabFolderEvent e) {
				Iterator it = tabs.keySet().iterator();
				while (it.hasNext()) {
					Object key = it.next();
					ChatTab tab = (ChatTab) tabs.get(key);
					if (tab.item == e.item) {
						tabs.remove(key);
						break;
					}
				}
			}
		});

		IMenuManager manager = getViewSite().getActionBars().getMenuManager();
		IAction timestampAction = new Action(Messages.MessagesView_ShowTimestamps, IAction.AS_CHECK_BOX) {
			public void run() {
				showTimestamps = !showTimestamps;
			}
		};
		timestampAction.setChecked(true);
		IAction clearChatLogAction = new Action(Messages.MessagesView_ClearChatLog) {
			public void run() {
				CTabItem item = tabFolder.getSelection();
				if (item != null) {
					Iterator iterator = tabs.values().iterator();
					while (iterator.hasNext()) {
						ChatTab tab = (ChatTab) iterator.next();
						if (tab.item == item) {
							if (MessageDialog.openConfirm(tabFolder.getShell(), Messages.MessagesView_ClearChatLogDialogTitle, Messages.MessagesView_ClearChatLogDialogMessage)) {
								synchronized (tab) {
									tab.chatText.setText(""); //$NON-NLS-1$
								}
							}
							return;
						}
					}
				}
			}
		};
		manager.add(clearChatLogAction);
		manager.add(timestampAction);

		redColor = new Color(parent.getDisplay(), 255, 0, 0);
		blueColor = new Color(parent.getDisplay(), 0, 0, 255);
	}

	public void dispose() {
		redColor.dispose();
		blueColor.dispose();
		super.dispose();
	}

	private ChatTab getTab(IChatMessageSender messageSender, ITypingMessageSender typingSender, ID localID, ID userID, String localName) {
		ChatTab tab = (ChatTab) tabs.get(userID);
		if (tab == null) {
			tab = new ChatTab(messageSender, typingSender, localID, userID, localName);
			tabs.put(userID, tab);
		}
		return tab;
	}

	/**
	 * Display a message to notify the current user that a typing event has
	 * occurred.
	 *
	 * @param event
	 *            the typing message event
	 */
	public void displayTypingNotification(ITypingMessageEvent event) {
		ChatTab tab = null;
		synchronized (tabs) {
			tab = (ChatTab) tabs.get(event.getFromID());
		}
		if (tab != null) {
			tab.showIsTyping(event.getTypingMessage().isTyping());
		}
	}

	/**
	 * Opens a new tab for conversing with a user.
	 *
	 * @param messageSender
	 *            the <tt>IChatMessageSender</tt> interface that can be used
	 *            to send messages to the other user
	 * @param typingSender
	 *            the <tt>ITypingMessageSender</tt> interface to notify the
	 *            other user that the current user is typing a message,
	 *            <tt>null</tt> if unsupported
	 * @param localID
	 *            the ID of the local user
	 * @param remoteID
	 *            the ID of the remote user
	 * @since 2.4
	 */
	public synchronized void openTab(IChatMessageSender messageSender, ITypingMessageSender typingSender, ID localID, ID remoteID, String localName) {
		Assert.isNotNull(messageSender);
		Assert.isNotNull(localID);
		Assert.isNotNull(remoteID);
		ChatTab tab = getTab(messageSender, typingSender, localID, remoteID, localName);
		// if there is only one tab, select this tab
		if (tabs.size() == 1) {
			tabFolder.setSelection(tab.item);
		}
	}

	private static String getLocalName(ID id) {
		IChatID cID = (IChatID) id.getAdapter(IChatID.class);
		return (cID == null) ? id.getName() : cID.getUsername();
	}

	/**
	 * @since 2.3
	 */
	public synchronized void openTab(IChatMessageSender messageSender, ITypingMessageSender typingSender, ID localID, ID remoteID) {
		openTab(messageSender, typingSender, localID, remoteID, getLocalName(remoteID));
	}

	/**
	 * @since 2.4
	 */
	public synchronized void selectTab(IChatMessageSender messageSender, ITypingMessageSender typingSender, ID localID, ID userID, String localName) {
		ChatTab tab = getTab(messageSender, typingSender, localID, userID, localName);
		tabFolder.setSelection(tab.item);
		tab.inputText.setFocus();
	}

	public synchronized void selectTab(IChatMessageSender messageSender, ITypingMessageSender typingSender, ID localID, ID userID) {
		selectTab(messageSender, typingSender, localID, userID, getLocalName(userID));
	}

	/**
	 * Display a chat message from a remote user in their designated chat box.
	 *
	 * @param message
	 *            a chat message that has been sent to the local user
	 */
	public synchronized void showMessage(IChatMessage message) {
		Assert.isNotNull(message);
		ID remoteID = message.getFromID();
		ChatTab tab = (ChatTab) tabs.get(remoteID);
		if (tab != null) {
			tab.append(remoteID, message.getBody());
		}
	}

	public void setFocus() {
		CTabItem item = tabFolder.getSelection();
		if (item != null) {
			for (Iterator it = tabs.values().iterator(); it.hasNext();) {
				ChatTab tab = (ChatTab) it.next();
				if (tab.item == item) {
					tab.inputText.setFocus();
					break;
				}
			}
		}
	}

	private class ChatTab {

		private CTabItem item;

		private StyledText chatText;

		private Text inputText;

		private IChatMessageSender icms;

		private ITypingMessageSender itms;

		private ID localID;
		private ID remoteID;

		private boolean sendTyping = false;

		private boolean isFirstMessage = true;

		private String localName;

		private ChatTab(IChatMessageSender icms, ITypingMessageSender itms, ID localID, ID remoteID, String localName) {
			this.icms = icms;
			this.itms = itms;
			this.localID = localID;
			this.remoteID = remoteID;
			this.localName = localName;
			constructWidgets();
			addListeners();
		}

		private void addListeners() {
			inputText.addKeyListener(new KeyAdapter() {
				public void keyPressed(KeyEvent e) {
					switch (e.keyCode) {
						case SWT.CR :
						case SWT.KEYPAD_CR :
							if (e.stateMask == 0) {
								String text = inputText.getText();
								inputText.setText(""); //$NON-NLS-1$
								try {
									if (!text.equals("")) { //$NON-NLS-1$
										icms.sendChatMessage(remoteID, text);
									}
									append(localID, text);
								} catch (ECFException ex) {
									String message = ex.getMessage();
									if (message == null || message.equals("")) { //$NON-NLS-1$
										message = ex.getStatus().getMessage();
										if (message == null || message.equals("")) { //$NON-NLS-1$
											message = ex.getCause().getMessage();
										}
									}

									if (message == null || message.equals("")) { //$NON-NLS-1$
										setContentDescription(Messages.MessagesView_CouldNotSendMessage);
									} else {
										setContentDescription(NLS.bind(Messages.MessagesView_CouldNotSendMessageCauseKnown, message));
									}
								}
								e.doit = false;
								sendTyping = false;
							}
							break;
					}
				}
			});

			inputText.addModifyListener(new ModifyListener() {
				public void modifyText(ModifyEvent e) {
					if (!sendTyping && itms != null) {
						sendTyping = true;
						try {
							itms.sendTypingMessage(remoteID, true, null);
						} catch (ECFException ex) {
							// ignored since this is not really that important
							return;
						}
					}
				}
			});

			ScrollBar vscrollBar = chatText.getVerticalBar();
			if (vscrollBar != null) {
				vscrollBar.addSelectionListener(scrollSelectionListener);
				chatText.addDisposeListener(new DisposeListener() {
					public void widgetDisposed(DisposeEvent e) {
						ScrollBar bar = chatText.getVerticalBar();
						if (bar != null)
							bar.removeSelectionListener(scrollSelectionListener);
					}
				});
			}
		}

		private SelectionListener scrollSelectionListener = new SelectionListener() {
			public void widgetDefaultSelected(SelectionEvent e) {
				// do nothing
			}

			public void widgetSelected(SelectionEvent e) {
				if (shouldScrollToEnd(chatText))
					boldTabTitle(false);
			}
		};

		private boolean shouldScrollToEnd(StyledText chatText1) {
			Point locAtEnd = chatText1.getLocationAtOffset(chatText1.getText().length());
			Rectangle bounds = chatText1.getBounds();
			if (locAtEnd.y > bounds.height + 5)
				return false;
			return true;
		}

		private void append(ID fromID, String body) {
			boolean scrollToEnd = shouldScrollToEnd(chatText);

			if (!isFirstMessage) {
				chatText.append(Text.DELIMITER);
			}
			int length = chatText.getCharCount();
			String name = localName;
			if (fromID.equals(remoteID)) {
				if (showTimestamps) {
					chatText.append(FORMATTER.format(new Date(System.currentTimeMillis())) + ' ');
					chatText.setStyleRange(new StyleRange(length, 13, redColor, null));
					length = chatText.getCharCount();
				}
				chatText.append(name + ": " + body); //$NON-NLS-1$
				chatText.setStyleRange(new StyleRange(length, name.length() + 1, redColor, null, SWT.BOLD));
				setContentDescription(""); //$NON-NLS-1$
				if (isFirstMessage) {
					final MessageNotificationPopup popup = new MessageNotificationPopup(getSite().getWorkbenchWindow(), tabFolder.getShell(), remoteID);
					popup.setContent(name, body);
					popup.open();

					new UIJob(tabFolder.getDisplay(), "Close Popup Job") { //$NON-NLS-1$
						public IStatus runInUIThread(IProgressMonitor monitor) {
							Shell shell = popup.getShell();
							if (shell != null && !shell.isDisposed()) {
								popup.close();
							}
							return Status.OK_STATUS;
						}
					}.schedule(5000);
				}
			} else {
				if (showTimestamps) {
					chatText.append(FORMATTER.format(new Date(System.currentTimeMillis())) + ' ');
					chatText.setStyleRange(new StyleRange(length, 13, blueColor, null));
					length = chatText.getCharCount();
				}
				chatText.append(name + ": " + body); //$NON-NLS-1$
				chatText.setStyleRange(new StyleRange(length, name.length() + 1, blueColor, null, SWT.BOLD));
			}
			isFirstMessage = false;
			if (scrollToEnd)
				chatText.invokeAction(ST.TEXT_END);
			boldTabTitle(!scrollToEnd);
		}

		private StyledText createStyledTextWidget(Composite parent) {
			try {
				SourceViewer result = new SourceViewer(parent, null, null, true, SWT.BORDER | SWT.WRAP | SWT.V_SCROLL | SWT.MULTI | SWT.READ_ONLY);
				result.configure(new TextSourceViewerConfiguration(EditorsUI.getPreferenceStore()));
				result.setDocument(new Document());
				return result.getTextWidget();
			} catch (Exception e) {
				Activator.getDefault().getLog().log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, IStatus.WARNING, Messages.MessagesView_WARNING_HYPERLINKING_NOT_AVAILABLE, e));
				return new StyledText(parent, SWT.BORDER | SWT.WRAP | SWT.V_SCROLL | SWT.MULTI | SWT.READ_ONLY);
			} catch (NoClassDefFoundError e) {
				Activator.getDefault().getLog().log(new Status(IStatus.WARNING, Activator.PLUGIN_ID, IStatus.WARNING, Messages.MessagesView_WARNING_HYPERLINKING_NOT_AVAILABLE, e));
				return new StyledText(parent, SWT.BORDER | SWT.WRAP | SWT.V_SCROLL | SWT.MULTI | SWT.READ_ONLY);
			}
		}

		private void boldTabTitle(boolean bold) {
			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 void constructWidgets() {
			item = new CTabItem(tabFolder, SWT.NONE);
			Composite parent = new Composite(tabFolder, SWT.NONE);
			parent.setLayout(new FillLayout());

			SashForm sash = new SashForm(parent, SWT.VERTICAL);

			chatText = createStyledTextWidget(sash);

			inputText = new Text(sash, SWT.MULTI | SWT.BORDER | SWT.V_SCROLL);

			sash.setWeights(WEIGHTS);

			Menu menu = new Menu(chatText);
			MenuItem mi = new MenuItem(menu, SWT.PUSH);
			mi.setText(Messages.MessagesView_Copy);
			mi.setImage(PlatformUI.getWorkbench().getSharedImages().getImage(org.eclipse.ui.ISharedImages.IMG_TOOL_COPY));
			mi.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					String text = chatText.getSelectionText();
					if (!text.equals("")) { //$NON-NLS-1$
						chatText.copy();
					}
				}
			});
			mi = new MenuItem(menu, SWT.PUSH);
			mi.setText(Messages.MessagesView_SelectAll);
			mi.addSelectionListener(new SelectionAdapter() {
				public void widgetSelected(SelectionEvent e) {
					chatText.selectAll();
				}
			});
			chatText.setMenu(menu);

			item.setControl(parent);
			item.setText(localName);
		}

		private void showIsTyping(boolean isTyping) {
			setContentDescription(isTyping ? NLS.bind(Messages.MessagesView_TypingNotification, localName) : ""); //$NON-NLS-1$
		}
	}

}
