/*******************************************************************************
 * Copyright (c) 2010, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.e4.ui.workbench.addons.dndaddon;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.eclipse.e4.core.services.events.IEventBroker;
import org.eclipse.e4.ui.internal.workbench.swt.AbstractPartRenderer;
import org.eclipse.e4.ui.model.application.ui.MUIElement;
import org.eclipse.e4.ui.model.application.ui.basic.MPartStack;
import org.eclipse.e4.ui.model.application.ui.basic.MWindow;
import org.eclipse.e4.ui.services.IStylingEngine;
import org.eclipse.e4.ui.widgets.ImageBasedFrame;
import org.eclipse.e4.ui.workbench.IPresentationEngine;
import org.eclipse.e4.ui.workbench.UIEvents;
import org.eclipse.e4.ui.workbench.modeling.EModelService;
import org.eclipse.jface.util.Geometry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.CTabFolder;
import org.eclipse.swt.custom.CTabItem;
import org.eclipse.swt.events.DragDetectListener;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.graphics.Region;
import org.eclipse.swt.graphics.Resource;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Tracker;
import org.osgi.service.event.EventHandler;

class DnDManager {
	private static final Rectangle offScreenRect = new Rectangle(10000, -10000, 1, 1);

	public static final int HOSTED = 1;
	public static final int GHOSTED = 2;
	public static final int SIMPLE = 3;
	private int feedbackStyle = SIMPLE;

	Collection<DragAgent> dragAgents = new ArrayList<>();
	Collection<DropAgent> dropAgents = new ArrayList<>();

	DnDInfo info;
	DragAgent dragAgent;

	private MWindow dragWindow;

	private Shell dragHost;
	private Control dragCtrl;

	private Tracker tracker;
	boolean dragging;

	private Shell overlayFrame;
	private List<Rectangle> frames = new ArrayList<>();

	DragDetectListener dragDetector = e -> {
		if (dragging || e.widget.isDisposed()) {
			return;
		}

		info.update(e);
		dragAgent = getDragAgent(info);
		if (dragAgent != null) {
			try {
				dragging = true;
				isModified = (e.stateMask & SWT.MOD1) != 0;
				startDrag();
			} finally {
				dragging = false;
			}
		}
	};

	public void addFrame(Rectangle newRect) {
		frames.add(newRect);
		updateOverlay();
	}

	private List<Image> images = new ArrayList<>();
	private List<Rectangle> imageRects = new ArrayList<>();

	protected boolean isModified;

	public void addImage(Rectangle imageRect, Image image) {
		imageRects.add(imageRect);
		images.add(image);
		updateOverlay();
	}

	public DnDManager(MWindow topLevelWindow) {
		dragWindow = topLevelWindow;
		info = new DnDInfo(topLevelWindow);

		// Dragging stacks and parts
		dragAgents.add(new PartDragAgent(this));

		dropAgents.add(new StackDropAgent(this));
		dropAgents.add(new SplitDropAgent2(this));
		dropAgents.add(new DetachedDropAgent(this));

		// dragging trim
		dragAgents.add(new IBFDragAgent(this));
		dropAgents.add(new TrimDropAgent(this));

		// Register a 'dragDetect' against any stacks that get created
		hookWidgets();

		getDragShell().addDisposeListener(e -> dispose());
	}

	/**
	 * Do any widget specific logic hookup. We should break the model generic logic away from the
	 * specific platform by moving this code into an SWT-specific subclass
	 */
	private void hookWidgets() {
		EventHandler stackWidgetHandler = event -> {
			MUIElement element = (MUIElement) event.getProperty(UIEvents.EventTags.ELEMENT);

			// Only add listeners for stacks in *this* window
			MWindow elementWin = getModelService().getTopLevelWindowFor(element);
			if (elementWin != dragWindow) {
				return;
			}

			// Listen for drags starting in CTabFolders
			if (element.getWidget() instanceof CTabFolder || element.getWidget() instanceof ImageBasedFrame) {
				Control ctrl = (Control) element.getWidget();

				// Ensure there's only one drag detect listener per ctrl
				ctrl.removeDragDetectListener(dragDetector);
				ctrl.addDragDetectListener(dragDetector);
			}
		};

		IEventBroker eventBroker = dragWindow.getContext().get(IEventBroker.class);
		eventBroker.subscribe(UIEvents.UIElement.TOPIC_WIDGET, stackWidgetHandler);
	}

	public MWindow getDragWindow() {
		return dragWindow;
	}

	public EModelService getModelService() {
		return dragWindow.getContext().get(EModelService.class);
	}

	public Shell getDragShell() {
		return (Shell) (dragWindow.getWidget() instanceof Shell ? dragWindow.getWidget() : null);
	}

	protected void dispose() {
		clearOverlay();

		if (overlayFrame != null && !overlayFrame.isDisposed()) {
			overlayFrame.dispose();
		}
		overlayFrame = null;

		for (DragAgent agent : dragAgents) {
			agent.dispose();
		}
		for (DropAgent agent : dropAgents) {
			agent.dispose();
		}
		info.curElement = null;
		info = null;
	}

	private void track() {
		Display.getCurrent().syncExec(() -> {
			info.update();
			dragAgent.track(info);

			// Hack: Spin the event loop
			update();
		});
	}

	protected void startDrag() {
		// Create a new tracker for this drag instance
		Shell activeShell = Display.getCurrent().getActiveShell();
		if (activeShell == null) {
			return;
		}

		tracker = new Tracker(activeShell, SWT.NULL);
		tracker.setStippled(true);
		setRectangle(offScreenRect);

		tracker.addKeyListener(new KeyListener() {
			@Override
			public void keyReleased(KeyEvent e) {
				if (e.keyCode == SWT.MOD1) {
					isModified = false;
					track();
				}
			}

			@Override
			public void keyPressed(KeyEvent e) {
				if (e.keyCode == SWT.MOD1) {
					isModified = true;
					track();
				}
			}
		});

		tracker.addListener(SWT.Move, event -> track());

		// Some control needs to capture the mouse during the drag or
		// other controls will interfere with the cursor
		getDragShell().setCapture(true);

		try {
			dragAgent.dragStart(info);

			// Run tracker until mouse up occurs or escape key pressed.
			boolean performDrop = tracker.open();

			// clean up
			finishDrag(performDrop);
		} finally {
			getDragShell().setCursor(null);
			getDragShell().setCapture(false);
		}
	}

	public void update() {
		Display.getCurrent().update();
	}

	/**
	 * @param performDrop
	 */
	private void finishDrag(boolean performDrop) {
		// Tear down any feedback
		if (tracker != null && !tracker.isDisposed()) {
			tracker.dispose();
			tracker = null;
		}

		if (overlayFrame != null) {
			overlayFrame.dispose();
			overlayFrame = null;
		}

		if (dragHost != null) {
			dragHost.dispose();
			dragHost = null;
		}

		// Perform either drop or cancel
		try {
			dragAgent.dragFinished(performDrop, info);
		} finally {
			dragAgent = null;
		}
	}

	public void setCursor(Cursor newCursor) {
		getDragShell().setCursor(newCursor);
	}

	public void setRectangle(Rectangle newRect) {
		if (tracker == null) {
			return;
		}

		Rectangle[] rectArray = { Geometry.copy(newRect) };
		tracker.setRectangles(rectArray);
	}

	public void hostElement(MUIElement element, int xOffset, int yOffset) {
		if (element == null) {
			if (dragHost != null && !dragHost.isDisposed()) {
				dragHost.dispose();
			}
			dragHost = null;
			return;
		}

		Shell parentShell = getDragShell();

		dragHost = new Shell(parentShell, SWT.NO_TRIM);
		dragHost.setBackground(parentShell.getDisplay().getSystemColor(SWT.COLOR_WHITE));
		dragHost.setLayout(new FillLayout());
		dragHost.setAlpha(120);
		Region shellRgn = new Region(dragHost.getDisplay());
		dragHost.setRegion(shellRgn);

		dragCtrl = (Control) element.getWidget();
		if (dragCtrl != null) {
			dragHost.setSize(dragCtrl.getSize());
		} else {
			dragHost.setSize(400, 400);
		}

		if (feedbackStyle == HOSTED) {
			// Special code to wrap the element in a CTF if it's coming from one
			MUIElement elementParent = element.getParent();
			if (elementParent instanceof MPartStack
					&& elementParent.getWidget() instanceof CTabFolder) {
				CTabFolder curCTF = (CTabFolder) elementParent.getWidget();
				dragHost.setSize(curCTF.getSize());
				CTabItem elementItem = getItemForElement(curCTF, element);
				assert (elementItem != null);

				IPresentationEngine renderingEngine = dragWindow.getContext().get(
						IPresentationEngine.class);
				CTabFolder ctf = new CTabFolder(dragHost, SWT.BORDER);
				CTabItem newItem = new CTabItem(ctf, SWT.NONE);
				newItem.setText(elementItem.getText());
				newItem.setImage(elementItem.getImage());

				element.getParent().getChildren().remove(element);
				dragCtrl = (Control) renderingEngine.createGui(element, ctf, getModelService()
						.getContainingContext(element));
				newItem.setControl(dragCtrl);
			}
		} else if (feedbackStyle == GHOSTED) {
			dragCtrl.setParent(dragHost);
			dragCtrl.setLocation(0, 0);
			dragHost.layout();
		}

		update();

		// Pass the shell to the info element for tracking
		dragHost.open();
		info.setDragHost(dragHost, xOffset, yOffset);
	}

	public void setDragHostVisibility(boolean visible) {
		if (dragHost == null || dragHost.isDisposed()) {
			return;
		}

		if (visible) {
			if (dragHost.getChildren().length > 0
					&& dragHost.getChildren()[0] instanceof CTabFolder) {
				CTabFolder ctf = (CTabFolder) dragHost.getChildren()[0];
				dragCtrl.setParent(ctf);
				dragHost.setVisible(true);
			} else {
				dragCtrl.setParent(dragHost);
			}
		} else {
			dragHost.setVisible(false);
		}
	}

	private CTabItem getItemForElement(CTabFolder elementCTF, MUIElement element) {
		for (CTabItem item : elementCTF.getItems()) {
			if (item.getData(AbstractPartRenderer.OWNING_ME) == element) {
				return item;
			}
		}
		return null;
	}

	public void clearOverlay() {
		frames.clear();
		images.clear();
		imageRects.clear();

		if (overlayFrame != null) {
			overlayFrame.setVisible(false);
		}
	}

	private void updateOverlay() {
		Rectangle bounds = getOverlayBounds();
		if (bounds == null) {
			clearOverlay();
			return;
		}

		if (overlayFrame == null) {
			overlayFrame = new Shell(getDragShell(), SWT.NO_TRIM | SWT.ON_TOP);
			overlayFrame.setData(DragAndDropUtil.IGNORE_AS_DROP_TARGET, Boolean.TRUE);
			overlayFrame.setBackground(Display.getCurrent().getSystemColor(SWT.COLOR_DARK_GREEN));
			overlayFrame.setAlpha(150);

			IStylingEngine stylingEngine = dragWindow.getContext().get(IStylingEngine.class);
			stylingEngine.setClassname(overlayFrame, "DragFeedback"); //$NON-NLS-1$
			stylingEngine.style(overlayFrame);

			overlayFrame.addPaintListener(e -> {
				for (int i = 0; i < images.size(); i++) {
					Image image = images.get(i);
					Rectangle iRect = imageRects.get(i);
					e.gc.drawImage(image, iRect.x, iRect.y);
				}
			});
		}

		// Reset for this set of overlays
		overlayFrame.setBounds(bounds);

		Region curRegion = overlayFrame.getRegion();
		if (curRegion != null && !curRegion.isDisposed()) {
			curRegion.dispose();
		}

		Region rgn = new Region();

		// Add frames
		for (Rectangle frameRect : frames) {
			int x = frameRect.x - bounds.x;
			int y = frameRect.y - bounds.y;

			if (frameRect.width > 6) {
				Rectangle outerBounds = new Rectangle(x - 3, y - 3, frameRect.width + 6,
						frameRect.height + 6);
				rgn.add(outerBounds);
				Rectangle innerBounds = new Rectangle(x, y, frameRect.width, frameRect.height);
				rgn.subtract(innerBounds);
			} else {
				Rectangle itemBounds = new Rectangle(x, y, frameRect.width, frameRect.height);
				rgn.add(itemBounds);
			}
		}

		// Add images
		for (int i = 0; i < images.size(); i++) {
			Rectangle ir = imageRects.get(i);
			Image im = images.get(i);

			int x = ir.x - bounds.x;
			int y = ir.y - bounds.y;

			rgn.add(x, y, im.getBounds().width, im.getBounds().height);
		}

		overlayFrame.setRegion(rgn);
		// Region object needs to be disposed at the right point in time
		addResourceDisposeListener(overlayFrame, rgn);
		overlayFrame.setVisible(true);
	}

	private void addResourceDisposeListener(Control control, final Resource resource) {
		control.addDisposeListener(e -> {
			if (!resource.isDisposed()) {
				resource.dispose();
			}
		});
	}

	private Rectangle getOverlayBounds() {
		Rectangle bounds = null;
		for (Rectangle fr : frames) {
			if (fr.width > 6) {
				Rectangle outerBounds = new Rectangle(fr.x - 3, fr.y - 3, fr.width + 6,
						fr.height + 6);
				if (bounds == null) {
					bounds = outerBounds;
				}
				bounds.add(outerBounds);
			} else {
				if (bounds == null) {
					bounds = fr;
				}
				bounds.add(fr);
			}
		}

		for (Rectangle ir : imageRects) {
			if (bounds == null) {
				bounds = ir;
			}
			bounds.add(ir);
		}

		return bounds;
	}

	public void frameRect(Rectangle bounds) {
		clearOverlay();
		if (bounds != null) {
			addFrame(bounds);
		}
	}

	public void addDragAgent(DragAgent newAgent) {
		if (!dragAgents.contains(newAgent)) {
			dragAgents.add(newAgent);
		}
	}

	public void removeDragAgent(DragAgent agentToRemove) {
		dragAgents.remove(agentToRemove);
	}

	public void addDropAgent(DropAgent newAgent) {
		if (!dropAgents.contains(newAgent)) {
			dropAgents.add(newAgent);
		}
	}

	public void removeDropAgent(DropAgent agentToRemove) {
		dropAgents.remove(agentToRemove);
	}

	private DragAgent getDragAgent(DnDInfo info) {
		for (DragAgent agent : dragAgents) {
			if (agent.canDrag(info)) {
				return agent;
			}
		}
		return null;
	}

	public DropAgent getDropAgent(MUIElement dragElement, DnDInfo info) {
		for (DropAgent agent : dropAgents) {
			if (agent.canDrop(dragElement, info)) {
				return agent;
			}
		}
		return null;
	}

	/**
	 * @return Return the feedback style
	 */
	public int getFeedbackStyle() {
		return feedbackStyle;
	}

	/**
	 * @param newBounds
	 */
	public void setHostBounds(Rectangle newBounds) {
		if (dragHost == null || dragHost.isDisposed()) {
			return;
		}

		info.setDragHostBounds(newBounds);
		update();
	}
}
