/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation 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
 *
 *******************************************************************************/
package org.eclipse.dltk.internal.ui.text.hover;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import org.eclipse.jface.text.AbstractInformationControlManager;
import org.eclipse.jface.text.DefaultInformationControl;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlExtension;
import org.eclipse.jface.text.IInformationControlExtension2;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.IViewportListener;
import org.eclipse.jface.text.Position;
import org.eclipse.jface.text.Region;
import org.eclipse.jface.text.TextViewer;
import org.eclipse.jface.text.source.Annotation;
import org.eclipse.jface.text.source.IAnnotationAccess;
import org.eclipse.jface.text.source.IAnnotationAccessExtension;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.jface.text.source.ISourceViewer;
import org.eclipse.jface.text.source.IVerticalRulerInfo;
import org.eclipse.jface.text.source.IVerticalRulerListener;
import org.eclipse.jface.text.source.VerticalRulerEvent;
import org.eclipse.jface.viewers.IDoubleClickListener;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.StyleRange;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.MenuEvent;
import org.eclipse.swt.events.MenuListener;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseTrackAdapter;
import org.eclipse.swt.events.MouseTrackListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Widget;

/**
 * A control that can display a number of annotations. The control can decide
 * how it layouts the annotations to present them to the user.
 * <p>
 * This class got moved here form Platform Text since it was not used there and
 * caused discouraged access warnings. It will be moved down again once
 * annotation roll-over support is provided by Platform Text.
 * </p>
 * <p>
 * Each annotation can have its custom context menu and hover.
 * </p>
 *
 * @since 3.2
 */
public class AnnotationExpansionControl implements IInformationControl,
		IInformationControlExtension, IInformationControlExtension2 {

	public interface ICallback {
		void run(IInformationControlExtension2 control);
	}

	/**
	 * Input used by the control to display the annotations. TODO move to
	 * top-level class TODO encapsulate fields
	 *
	 * @since 3.0
	 */
	public static class AnnotationHoverInput {
		public Annotation[] fAnnotations;
		public ISourceViewer fViewer;
		public IVerticalRulerInfo fRulerInfo;
		public IVerticalRulerListener fAnnotationListener;
		public IDoubleClickListener fDoubleClickListener;
		public ICallback redoAction;
		public IAnnotationModel model;
	}

	private final class Item {
		Annotation fAnnotation;
		Canvas canvas;
		StyleRange[] oldStyles;

		public void selected() {
			Display disp = fShell.getDisplay();
			canvas.setCursor(fHandCursor);
			// TODO: shade - for now: set grey background
			canvas.setBackground(getSelectionColor(disp));

			// highlight the viewer background at its position
			oldStyles = setViewerBackground(fAnnotation);

			// set the selection
			fSelection = this;

			if (fHoverManager != null)
				fHoverManager.showInformation();

			if (fInput.fAnnotationListener != null) {
				VerticalRulerEvent event = new VerticalRulerEvent(fAnnotation);
				fInput.fAnnotationListener.annotationSelected(event);
			}

		}

		public void defaultSelected() {
			if (fInput.fAnnotationListener != null) {
				VerticalRulerEvent event = new VerticalRulerEvent(fAnnotation);
				fInput.fAnnotationListener.annotationDefaultSelected(event);
			}

			dispose();
		}

		public void deselect() {
			// hide the popup
			// fHoverManager.disposeInformationControl();

			// deselect
			fSelection = null;

			resetViewerBackground(oldStyles);
			oldStyles = null;

			Display disp = fShell.getDisplay();
			canvas.setCursor(null);
			// TODO: remove shading - for now: set standard background
			canvas.setBackground(
					disp.getSystemColor(SWT.COLOR_INFO_BACKGROUND));

		}

	}

	/**
	 * Disposes of an item
	 */
	private final static class MyDisposeListener implements DisposeListener {
		@Override
		public void widgetDisposed(DisposeEvent e) {
			Item item = (Item) ((Widget) e.getSource()).getData();
			item.deselect();
			item.canvas = null;
			item.fAnnotation = null;
			item.oldStyles = null;

			((Widget) e.getSource()).setData(null);
		}
	}

	/**
	 * Listener on context menu invocation on the items
	 */
	private final class MyMenuDetectListener implements Listener {
		@Override
		public void handleEvent(Event event) {
			if (event.type == SWT.MenuDetect) {
				// TODO: show per-item menu
				// for now: show ruler context menu
				if (fInput != null) {
					Control ruler = fInput.fRulerInfo.getControl();
					if (ruler != null && !ruler.isDisposed()) {
						Menu menu = ruler.getMenu();
						if (menu != null && !menu.isDisposed()) {
							menu.setLocation(event.x, event.y);
							menu.addMenuListener(new MenuListener() {

								@Override
								public void menuHidden(MenuEvent e) {
									dispose();
								}

								@Override
								public void menuShown(MenuEvent e) {
								}

							});
							menu.setVisible(true);
						}
					}
				}
			}
		}
	}

	/**
	 * Listener on mouse events on the items.
	 */
	private final class MyMouseListener extends MouseAdapter {
		@Override
		public void mouseDoubleClick(MouseEvent e) {
			Item item = (Item) ((Widget) e.getSource()).getData();
			if (e.button == 1 && item.fAnnotation == fInput.fAnnotations[0]
					&& fInput.fDoubleClickListener != null) {
				fInput.fDoubleClickListener.doubleClick(null);
				// special code for JDT to renew the annotation set.
				if (fInput.redoAction != null)
					fInput.redoAction.run(AnnotationExpansionControl.this);
			}
			// dispose();
			// TODO special action to invoke double-click action on the vertical
			// ruler
			// how about
			// Canvas can= (Canvas) e.getSource();
			// Annotation a= (Annotation) can.getData();
			// if (a != null) {
			// a.getDoubleClickAction().run();
			// }
		}

		@Override
		public void mouseDown(MouseEvent e) {
			Item item = (Item) ((Widget) e.getSource()).getData();
			// TODO for now, to make double click work: disable single click on
			// the first item
			// disable later when the annotationlistener selectively handles
			// input
			if (item != null && e.button == 1) // && item.fAnnotation !=
												// fInput.fAnnotations[0])
				item.defaultSelected();
		}
	}

	/**
	 * Listener on mouse track events on the items.
	 */
	private final class MyMouseTrackListener implements MouseTrackListener {
		@Override
		public void mouseEnter(MouseEvent e) {
			Item item = (Item) ((Widget) e.getSource()).getData();
			if (item != null)
				item.selected();
		}

		@Override
		public void mouseExit(MouseEvent e) {

			Item item = (Item) ((Widget) e.getSource()).getData();
			if (item != null)
				item.deselect();

			// if the event lies outside the entire popup, dispose
			org.eclipse.swt.graphics.Region region = fShell.getRegion();
			Canvas can = (Canvas) e.getSource();
			Point p = can.toDisplay(e.x, e.y);
			if (region == null) {
				Rectangle bounds = fShell.getBounds();
				// p= fShell.toControl(p);
				if (!bounds.contains(p))
					dispose();
			} else {
				p = fShell.toControl(p);
				if (!region.contains(p))
					dispose();
			}

		}

		@Override
		public void mouseHover(MouseEvent e) {
			if (fHoverManager == null) {
				fHoverManager = new HoverManager();
				fHoverManager.takesFocusWhenVisible(false);
				fHoverManager.install(fComposite);
				fHoverManager.showInformation();
			}
		}
	}

	/**
	 * @since 3.0
	 */
	public class LinearLayouter {

		private static final int ANNOTATION_SIZE = 14;
		private static final int BORDER_WIDTH = 2;

		public Layout getLayout(int itemCount) {
			// simple layout: a row of items
			GridLayout layout = new GridLayout(itemCount, true);
			layout.horizontalSpacing = 1;
			layout.verticalSpacing = 0;
			layout.marginHeight = 1;
			layout.marginWidth = 1;
			return layout;
		}

		public Object getLayoutData() {
			GridData gridData = new GridData(ANNOTATION_SIZE + 2 * BORDER_WIDTH,
					ANNOTATION_SIZE + 2 * BORDER_WIDTH);
			gridData.horizontalAlignment = GridData.CENTER;
			gridData.verticalAlignment = GridData.CENTER;
			return gridData;
		}

		public int getAnnotationSize() {
			return ANNOTATION_SIZE;
		}

		public int getBorderWidth() {
			return BORDER_WIDTH;
		}

		public org.eclipse.swt.graphics.Region getShellRegion(int itemCount) {
			// no special region - set to null for default shell size
			return null;
		}

	}

	/**
	 * Listener on paint events on the items. Paints the annotation image on the
	 * given <code>GC</code>.
	 */
	private final class MyPaintListener implements PaintListener {
		@Override
		public void paintControl(PaintEvent e) {
			Canvas can = (Canvas) e.getSource();
			Annotation a = ((Item) can.getData()).fAnnotation;
			if (a != null) {
				Rectangle rect = new Rectangle(fLayouter.getBorderWidth(),
						fLayouter.getBorderWidth(),
						fLayouter.getAnnotationSize(),
						fLayouter.getAnnotationSize());
				if (fAnnotationAccessExtension != null)
					fAnnotationAccessExtension.paint(a, e.gc, can, rect);
			}
		}
	}

	/**
	 * Our own private hover manager used to shop per-item pop-ups.
	 */
	private final class HoverManager extends AbstractInformationControlManager {

		public HoverManager() {
			super(parent -> new DefaultInformationControl(parent));

			setMargins(5, 10);
			setAnchor(ANCHOR_BOTTOM);
			setFallbackAnchors(
					new Anchor[] { ANCHOR_BOTTOM, ANCHOR_LEFT, ANCHOR_RIGHT });
		}

		@Override
		protected void computeInformation() {
			if (fSelection != null) {
				Rectangle subjectArea = fSelection.canvas.getBounds();
				Annotation annotation = fSelection.fAnnotation;
				String msg;
				if (annotation != null)
					msg = annotation.getText();
				else
					msg = null;

				setInformation(msg, subjectArea);
			}
		}

	}

	/** Model data. */
	protected AnnotationHoverInput fInput;
	/** The control's shell */
	private Shell fShell;
	/** The composite combining all the items. */
	protected Composite fComposite;
	/** The hand cursor. */
	private Cursor fHandCursor;
	/**
	 * The currently selected item, or <code>null</code> if none is selected.
	 */
	private Item fSelection;
	/** The hover manager for the per-item hovers. */
	private HoverManager fHoverManager;
	/** The annotation access extension. */
	private IAnnotationAccessExtension fAnnotationAccessExtension;

	/* listener legion */
	private final MyPaintListener fPaintListener;
	private final MyMouseTrackListener fMouseTrackListener;
	private final MyMouseListener fMouseListener;
	private final MyMenuDetectListener fMenuDetectListener;
	private final DisposeListener fDisposeListener;
	private final IViewportListener fViewportListener;

	private LinearLayouter fLayouter;

	/**
	 * Creates a new control.
	 *
	 * @param parent
	 * @param shellStyle
	 * @param access
	 */
	public AnnotationExpansionControl(Shell parent, int shellStyle,
			IAnnotationAccess access) {
		fPaintListener = new MyPaintListener();
		fMouseTrackListener = new MyMouseTrackListener();
		fMouseListener = new MyMouseListener();
		fMenuDetectListener = new MyMenuDetectListener();
		fDisposeListener = new MyDisposeListener();
		fViewportListener = verticalOffset -> dispose();
		fLayouter = new LinearLayouter();

		if (access instanceof IAnnotationAccessExtension)
			fAnnotationAccessExtension = (IAnnotationAccessExtension) access;

		fShell = new Shell(parent, shellStyle | SWT.NO_FOCUS | SWT.ON_TOP);
		Display display = fShell.getDisplay();
		fShell.setBackground(display.getSystemColor(SWT.COLOR_BLACK));
		fComposite = new Composite(fShell,
				SWT.NO_FOCUS | SWT.NO_REDRAW_RESIZE | SWT.NO_TRIM);
		// fComposite= new Composite(fShell, SWT.NO_FOCUS | SWT.NO_REDRAW_RESIZE
		// | SWT.NO_TRIM | SWT.V_SCROLL);

		GridLayout layout = new GridLayout(1, true);
		layout.marginHeight = 0;
		layout.marginWidth = 0;
		fShell.setLayout(layout);

		GridData data = new GridData(GridData.FILL_BOTH);
		data.heightHint = fLayouter.getAnnotationSize()
				+ 2 * fLayouter.getBorderWidth() + 4;
		fComposite.setLayoutData(data);
		fComposite.addMouseTrackListener(new MouseTrackAdapter() {

			@Override
			public void mouseExit(MouseEvent e) {
				if (fComposite == null)
					return;
				Control[] children = fComposite.getChildren();
				Rectangle bounds = null;
				for (int i = 0; i < children.length; i++) {
					if (bounds == null)
						bounds = children[i].getBounds();
					else
						bounds.add(children[i].getBounds());
					if (bounds.contains(e.x, e.y))
						return;
				}

				// if none of the children contains the event, we leave the
				// popup
				dispose();
			}

		});

		// fComposite.getVerticalBar().addListener(SWT.Selection, new Listener()
		// {
		//
		// public void handleEvent(Event event) {
		// Rectangle bounds= fShell.getBounds();
		// int x= bounds.x - fLayouter.getAnnotationSize() -
		// fLayouter.getBorderWidth();
		// int y= bounds.y;
		// fShell.setBounds(x, y, bounds.width, bounds.height);
		// }
		//
		// });

		fHandCursor = new Cursor(display, SWT.CURSOR_HAND);
		fShell.setCursor(fHandCursor);
		fComposite.setCursor(fHandCursor);

		setInfoSystemColor();
	}

	private void setInfoSystemColor() {
		Display display = fShell.getDisplay();
		setForegroundColor(display.getSystemColor(SWT.COLOR_INFO_FOREGROUND));
		setBackgroundColor(display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));
	}

	@Override
	public void setInformation(String information) {
		setInput(null);
	}

	@Override
	public void setInput(Object input) {
		if (fInput != null && fInput.fViewer != null)
			fInput.fViewer.removeViewportListener(fViewportListener);

		if (input instanceof AnnotationHoverInput)
			fInput = (AnnotationHoverInput) input;
		else
			fInput = null;

		inputChanged(fInput, null);
	}

	protected void inputChanged(Object newInput, Object newSelection) {
		refresh();
	}

	protected void refresh() {
		adjustItemNumber();

		if (fInput == null)
			return;

		if (fInput.fAnnotations == null)
			return;

		if (fInput.fViewer != null)
			fInput.fViewer.addViewportListener(fViewportListener);

		fShell.setRegion(fLayouter.getShellRegion(fInput.fAnnotations.length));

		Layout layout = fLayouter.getLayout(fInput.fAnnotations.length);
		fComposite.setLayout(layout);

		Control[] children = fComposite.getChildren();
		for (int i = 0; i < fInput.fAnnotations.length; i++) {
			Canvas canvas = (Canvas) children[i];
			Item item = new Item();
			item.canvas = canvas;
			item.fAnnotation = fInput.fAnnotations[i];
			canvas.setData(item);
			canvas.redraw();
		}

	}

	protected void adjustItemNumber() {
		if (fComposite == null)
			return;

		Control[] children = fComposite.getChildren();
		int oldSize = children.length;
		int newSize = fInput == null ? 0 : fInput.fAnnotations.length;

		Display display = fShell.getDisplay();

		// add missing items
		for (int i = oldSize; i < newSize; i++) {
			Canvas canvas = new Canvas(fComposite, SWT.NONE);
			Object gridData = fLayouter.getLayoutData();
			canvas.setLayoutData(gridData);
			canvas.setBackground(
					display.getSystemColor(SWT.COLOR_INFO_BACKGROUND));

			canvas.addPaintListener(fPaintListener);

			canvas.addMouseTrackListener(fMouseTrackListener);

			canvas.addMouseListener(fMouseListener);

			canvas.addListener(SWT.MenuDetect, fMenuDetectListener);

			canvas.addDisposeListener(fDisposeListener);
		}

		// dispose of exceeding resources
		for (int i = oldSize; i > newSize; i--) {
			Item item = (Item) children[i - 1].getData();
			item.deselect();
			children[i - 1].dispose();
		}

	}

	@Override
	public void setVisible(boolean visible) {
		fShell.setVisible(visible);
	}

	@Override
	public void dispose() {
		if (fShell != null) {
			if (!fShell.isDisposed())
				fShell.dispose();
			fShell = null;
			fComposite = null;
			if (fHandCursor != null)
				fHandCursor.dispose();
			fHandCursor = null;
			if (fHoverManager != null)
				fHoverManager.dispose();
			fHoverManager = null;
			fSelection = null;
		}
	}

	@Override
	public boolean hasContents() {
		return fInput.fAnnotations != null && fInput.fAnnotations.length > 0;
	}

	@Override
	public void setSizeConstraints(int maxWidth, int maxHeight) {
		// fMaxWidth= maxWidth;
		// fMaxHeight= maxHeight;
	}

	@Override
	public Point computeSizeHint() {
		return fShell.computeSize(SWT.DEFAULT, SWT.DEFAULT);
	}

	@Override
	public void setLocation(Point location) {
		fShell.setLocation(location);
	}

	@Override
	public void setSize(int width, int height) {
		fShell.setSize(width, height);
	}

	@Override
	public void addDisposeListener(DisposeListener listener) {
		fShell.addDisposeListener(listener);
	}

	@Override
	public void removeDisposeListener(DisposeListener listener) {
		fShell.removeDisposeListener(listener);
	}

	@Override
	public void setForegroundColor(Color foreground) {
		fComposite.setForeground(foreground);
	}

	@Override
	public void setBackgroundColor(Color background) {
		fComposite.setBackground(background);
	}

	@Override
	public boolean isFocusControl() {
		if (fComposite.isFocusControl())
			return true;

		Control[] children = fComposite.getChildren();
		for (int i = 0; i < children.length; i++) {
			if (children[i].isFocusControl())
				return true;
		}
		return false;
	}

	@Override
	public void setFocus() {
		fShell.forceFocus();
	}

	@Override
	public void addFocusListener(FocusListener listener) {
		fShell.addFocusListener(listener);
	}

	@Override
	public void removeFocusListener(FocusListener listener) {
		fShell.removeFocusListener(listener);
	}

	private StyleRange[] setViewerBackground(Annotation annotation) {
		StyledText text = fInput.fViewer.getTextWidget();
		if (text == null || text.isDisposed())
			return null;

		Display disp = text.getDisplay();

		Position pos = fInput.model.getPosition(annotation);
		if (pos == null)
			return null;

		IRegion region = ((TextViewer) fInput.fViewer)
				.modelRange2WidgetRange(new Region(pos.offset, pos.length));
		if (region == null)
			return null;

		StyleRange[] ranges = text.getStyleRanges(region.getOffset(),
				region.getLength());

		List<StyleRange> undoRanges = new ArrayList<>(ranges.length);
		for (int i = 0; i < ranges.length; i++) {
			undoRanges.add((StyleRange) ranges[i].clone());
		}

		int offset = region.getOffset();
		StyleRange current = undoRanges.size() > 0
				? (StyleRange) undoRanges.get(0)
				: null;
		int curStart = current != null ? current.start
				: region.getOffset() + region.getLength();
		int curEnd = current != null ? current.start + current.length : -1;
		int index = 0;

		// fill no-style regions
		while (curEnd < region.getOffset() + region.getLength()) {
			// add empty range
			if (curStart > offset) {
				StyleRange undoRange = new StyleRange(offset, curStart - offset,
						null, null);
				undoRanges.add(index, undoRange);
				index++;
			}

			// step
			index++;
			if (index < undoRanges.size()) {
				offset = curEnd;
				current = undoRanges.get(index);
				curStart = current.start;
				curEnd = current.start + current.length;
			} else if (index == undoRanges.size()) {
				// last one
				offset = curEnd;
				current = null;
				curStart = region.getOffset() + region.getLength();
				curEnd = -1;
			} else
				curEnd = region.getOffset() + region.getLength();
		}

		// create modified styles (with background)
		List<StyleRange> shadedRanges = new ArrayList<>(undoRanges.size());
		for (Iterator<StyleRange> it = undoRanges.iterator(); it.hasNext();) {
			StyleRange range = (StyleRange) it.next().clone();
			shadedRanges.add(range);
			range.background = getHighlightColor(disp);
		}

		// set the ranges one by one
		for (Iterator<StyleRange> iter = shadedRanges.iterator(); iter
				.hasNext();) {
			text.setStyleRange(iter.next());

		}

		return undoRanges.toArray(undoRanges.toArray(new StyleRange[0]));
	}

	private void resetViewerBackground(StyleRange[] oldRanges) {

		if (oldRanges == null)
			return;

		if (fInput == null)
			return;

		StyledText text = fInput.fViewer.getTextWidget();
		if (text == null || text.isDisposed())
			return;

		// set the ranges one by one
		for (int i = 0; i < oldRanges.length; i++) {
			text.setStyleRange(oldRanges[i]);
		}
	}

	private Color getHighlightColor(Display disp) {
		return disp.getSystemColor(SWT.COLOR_GRAY);
	}

	private Color getSelectionColor(Display disp) {
		return disp.getSystemColor(SWT.COLOR_GRAY);
	}

}
