/*******************************************************************************
 * Copyright (c) 2011, 2018 The Eclipse Foundation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     The Eclipse Foundation - initial API and implementation
 *     Yatta Solutions - public API (bug 432803), drag&drop (bug 433333)
 *******************************************************************************/
package org.eclipse.epp.internal.mpc.ui.wizards;

import java.lang.reflect.Field;

import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.epp.internal.mpc.ui.MarketplaceClientUi;
import org.eclipse.epp.internal.mpc.ui.MarketplaceClientUiPlugin;
import org.eclipse.epp.mpc.ui.MarketplaceUrlHandler;
import org.eclipse.epp.mpc.ui.MarketplaceUrlHandler.SolutionInstallationInfo;
import org.eclipse.jface.util.Util;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.dnd.DND;
import org.eclipse.swt.dnd.DropTarget;
import org.eclipse.swt.dnd.DropTargetAdapter;
import org.eclipse.swt.dnd.DropTargetEvent;
import org.eclipse.swt.dnd.DropTargetListener;
import org.eclipse.swt.dnd.Transfer;
import org.eclipse.swt.dnd.TransferData;
import org.eclipse.swt.dnd.URLTransfer;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IPageListener;
import org.eclipse.ui.IPartListener2;
import org.eclipse.ui.IPartService;
import org.eclipse.ui.IPerspectiveDescriptor;
import org.eclipse.ui.IPerspectiveListener;
import org.eclipse.ui.IStartup;
import org.eclipse.ui.IWindowListener;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchPartReference;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.UIJob;

/**
 * @author Benjamin Muskalla
 * @author Carsten Reckord
 */
public class MarketplaceDropAdapter implements IStartup {

	private static final int[] PREFERRED_DROP_OPERATIONS = { DND.DROP_DEFAULT, DND.DROP_COPY, DND.DROP_MOVE,
			DND.DROP_LINK };

	private static final int DROP_OPERATIONS = DND.DROP_MOVE | DND.DROP_COPY | DND.DROP_LINK | DND.DROP_DEFAULT;

	private final DropTargetAdapter dropListener = new MarketplaceDropTargetListener();

	private final WorkbenchListener workbenchListener = new WorkbenchListener();

	private Transfer[] transferAgents;

	@Override
	public void earlyStartup() {
		UIJob registerJob = new UIJob(Display.getDefault(), Messages.MarketplaceDropAdapter_0) {
			{
				setPriority(Job.SHORT);
				setSystem(true);
			}

			@Override
			public IStatus runInUIThread(IProgressMonitor monitor) {
				IWorkbench workbench = PlatformUI.getWorkbench();
				workbench.addWindowListener(workbenchListener);
				IWorkbenchWindow[] workbenchWindows = workbench
						.getWorkbenchWindows();
				for (IWorkbenchWindow window : workbenchWindows) {
					workbenchListener.hookWindow(window);
				}
				return Status.OK_STATUS;
			}

		};
		registerJob.schedule();
	}

	public void installDropTarget(final Shell shell) {
		hookUrlTransfer(shell, dropListener);
	}

	private DropTarget hookUrlTransfer(final Shell shell, DropTargetAdapter dropListener) {
		DropTarget target = findDropTarget(shell);
		if (target != null) {
			//target exists, get it and check proper registration
			registerWithExistingTarget(target);
		} else {
			target = new DropTarget(shell, DROP_OPERATIONS);
			if (transferAgents == null) {
				transferAgents = new Transfer[] { URLTransfer.getInstance() };
			}
			target.setTransfer(transferAgents);
		}
		registerDropListener(target, dropListener);

		Control[] children = shell.getChildren();
		for (Control child : children) {
			hookRecursive(child, dropListener);
		}
		return target;
	}

	private void registerDropListener(DropTarget target, DropTargetListener dropListener) {
		target.removeDropListener(dropListener);
		target.addDropListener(dropListener);
	}

	private void hookRecursive(Control child, DropTargetListener dropListener) {
		DropTarget childTarget = findDropTarget(child);
		if (childTarget != null) {
			registerWithExistingTarget(childTarget);
			registerDropListener(childTarget, dropListener);
		}
		if (child instanceof Composite) {
			Composite composite = (Composite) child;
			// Bug 485245 - avoid UI freezes for deeply nested widget trees
			composite.getDisplay().asyncExec(() -> {
				Control[] children = composite.getChildren();
				for (Control control : children) {
					hookRecursive(control, dropListener);
				}
			});
		}
	}

	private void registerWithExistingTarget(DropTarget target) {
		Transfer[] transfers = target.getTransfer();
		boolean exists = false;
		if (transfers != null) {
			for (Transfer transfer : transfers) {
				if (transfer instanceof URLTransfer) {
					exists = true;
					break;
				}
			}
			if (!exists) {
				Transfer[] newTransfers = new Transfer[transfers.length + 1];
				System.arraycopy(transfers, 0, newTransfers, 0, transfers.length);
				newTransfers[transfers.length] = URLTransfer.getInstance();
				target.setTransfer(newTransfers);
			}
		}
	}

	private DropTarget findDropTarget(Control control) {
		if (control.isDisposed()) {
			return null;
		}
		Object object = control.getData(DND.DROP_TARGET_KEY);
		if (object instanceof DropTarget) {
			return (DropTarget) object;
		}
		return null;
	}

	protected void proceedInstallation(String url) {
		SolutionInstallationInfo info = MarketplaceUrlHandler.createSolutionInstallInfo(url);
		if (info != null) {
			MarketplaceUrlHandler.triggerInstall(info);
		}
	}

	protected void proceedFavorites(String url) {
		MarketplaceUrlHandler.triggerFavorites(url);
	}

	protected boolean acceptSolutionUrl(final String url) {
		return MarketplaceUrlHandler.isPotentialSolution(url);
	}

	protected boolean acceptFavoritesListUrl(final String url) {
		return MarketplaceUrlHandler.isPotentialFavoritesList(url);
	}

	private class MarketplaceDropTargetListener extends DropTargetAdapter {

		@Override
		public void dragEnter(DropTargetEvent e) {
			updateDragDetails(e);
		}

		@Override
		public void dragOver(DropTargetEvent e) {
			updateDragDetails(e);
		}

		@Override
		public void dragLeave(DropTargetEvent e) {
			if (e.detail == DND.DROP_NONE) {
				setDropOperation(e);
			}
		}

		@Override
		public void dropAccept(DropTargetEvent e) {
			updateDragDetails(e);
		}

		@Override
		public void dragOperationChanged(DropTargetEvent e) {
			updateDragDetails(e);
		}

		private void setDropOperation(DropTargetEvent e) {
			int allowedOperations = e.operations;
			for (int op : PREFERRED_DROP_OPERATIONS) {
				if ((allowedOperations & op) != 0) {
					traceDropOperation(op);
					e.detail = op;
					return;
				}
			}
			e.detail = allowedOperations;
		}

		private void updateDragDetails(DropTargetEvent e) {
			if (dropTargetIsValid(e, false)) {
				setDropOperation(e);
			}
		}

		private boolean dropTargetIsValid(DropTargetEvent e, boolean isDrop) {
			if (URLTransfer.getInstance().isSupportedType(e.currentDataType)) {
				//on Windows, we get the URL already during drag operations...
				//FIXME find a way to check the URL early on other platforms, too...
				if (isDrop || Util.isWindows()) {
					if (e.data == null && !extractEventData(e)) {
						traceMissingEventData(e);
						//... but if we don't, it's no problem, unless this is already
						//the final drop event
						return !isDrop;
					}
					final String url = getUrl(e.data);
					if (acceptSolutionUrl(url)) {
						return true;
					} else if (acceptFavoritesListUrl(url)) {
						return true;
					} else {
						traceInvalidEventData(e);
						return false;
					}
				}
				return true;
			}
			traceUnsupportedDataType(e);
			return false;
		}

		private boolean extractEventData(DropTargetEvent e) {
			TransferData transferData = e.currentDataType;
			if (transferData != null) {
				Object data = URLTransfer.getInstance().nativeToJava(transferData);
				if (data != null && getUrl(data) != null) {
					e.data = data;
					return true;
				}
			}
			return false;
		}

		@Override
		public void drop(DropTargetEvent event) {
			if (!URLTransfer.getInstance().isSupportedType(event.currentDataType)) {
				traceUnsupportedDataType(event);
				//ignore
				return;
			}
			if (event.data == null) {
				traceMissingEventData(event);
				//reject
				event.detail = DND.DROP_NONE;
				return;
			}
			if (!dropTargetIsValid(event, true)) {
				//reject
				event.detail = DND.DROP_NONE;
				return;
			}
			final String url = getUrl(event.data);
			if (acceptSolutionUrl(url)) {
				//http://marketplace.eclipse.org/marketplace-client-intro?mpc_install=1640500
				DropTarget source = (DropTarget) event.getSource();
				Display display = source.getDisplay();
				display.asyncExec(() -> proceedInstallation(url));
			} else if (acceptFavoritesListUrl(url)) {
				//https://marketplace.eclipse.org/user/xxx/favorites
				DropTarget source = (DropTarget) event.getSource();
				Display display = source.getDisplay();
				display.asyncExec(() -> proceedFavorites(url));
			} else {
				traceInvalidEventData(event);
			}
		}

		private void traceDropOperation(int op) {
			if (MarketplaceClientUiPlugin.DEBUG) {
				MarketplaceClientUiPlugin.trace(MarketplaceClientUiPlugin.DROP_ADAPTER_DEBUG_OPTION,
						"Updating drop event: Setting drop operation to {0}", op); //$NON-NLS-1$
			}
		}

		private void traceInvalidEventData(DropTargetEvent event) {
			if (MarketplaceClientUiPlugin.DEBUG) {
				MarketplaceClientUiPlugin.trace(MarketplaceClientUiPlugin.DROP_ADAPTER_DEBUG_OPTION,
						"Drop event: Data is not a solution url: {0}", event.data, new Throwable()); //$NON-NLS-1$
			}
		}

		private void traceMissingEventData(DropTargetEvent event) {
			if (MarketplaceClientUiPlugin.DEBUG) {
				MarketplaceClientUiPlugin.trace(MarketplaceClientUiPlugin.DROP_ADAPTER_DEBUG_OPTION,
						"Missing drop event data {0}", event.data, new Throwable()); //$NON-NLS-1$
			}
		}

		private void traceUnsupportedDataType(DropTargetEvent event) {
			if (MarketplaceClientUiPlugin.DEBUG) {
				MarketplaceClientUiPlugin.trace(MarketplaceClientUiPlugin.DROP_ADAPTER_DEBUG_OPTION,
						"Unsupported drop data type {0}", traceTransferData(event.currentDataType), new Throwable()); //$NON-NLS-1$
			}
		}

		private Object traceTransferData(TransferData data) {
			if (MarketplaceClientUiPlugin.DEBUG) {
				return new TransferDataTraceFormatter(data);
			}
			return null;
		}

		private String getUrl(Object eventData) {
			if (eventData == null) {
				return null;
			}
			if (eventData == null || !(eventData instanceof String)) {
				return null;
			}
			// Depending on the form the link and browser/os,
			// we get the url twice in the data separated by new lines
			String[] dataLines = ((String) eventData).split(System.getProperty("line.separator")); //$NON-NLS-1$
			String url = dataLines[0];
			return url;
		}
	}

	private static final class TransferDataTraceFormatter {
		private static final Field TYPE_FIELD;

		static {
			Field typeField = null;
			try {
				typeField = TransferData.class.getDeclaredField("type"); //$NON-NLS-1$
				typeField.setAccessible(true);
			} catch (Exception e) {
			}
			TYPE_FIELD = typeField;
		}

		private final TransferData transferData;

		public TransferDataTraceFormatter(TransferData transferData) {
			this.transferData = transferData;
		}

		@Override
		public String toString() {
			if (transferData == null) {
				return null;
			}
			return "TransferData[type=" + getType() + "]"; //$NON-NLS-1$//$NON-NLS-2$
		}

		private String getType() {
			if (TYPE_FIELD == null) {
				return "<unknown>"; //$NON-NLS-1$
			}
			try {
				Object type = TYPE_FIELD.get(transferData);
				return type == null ? null : type.toString();
			} catch (IllegalArgumentException e) {
				return "<unknown:" + transferData.getClass() + ">"; //$NON-NLS-1$ //$NON-NLS-2$
			} catch (IllegalAccessException e) {
				return "<inaccessible>"; //$NON-NLS-1$
			}
		}
	}

	private class WorkbenchListener implements IPartListener2, IPageListener, IPerspectiveListener, IWindowListener {

		@Override
		public void perspectiveActivated(IWorkbenchPage page, IPerspectiveDescriptor perspective) {
			pageChanged(page);
		}

		@Override
		public void perspectiveChanged(IWorkbenchPage page, IPerspectiveDescriptor perspective, String changeId) {
		}

		@Override
		public void pageActivated(IWorkbenchPage page) {
			pageChanged(page);
		}

		@Override
		public void pageClosed(IWorkbenchPage page) {
		}

		@Override
		public void pageOpened(IWorkbenchPage page) {
			pageChanged(page);
		}

		private void pageChanged(IWorkbenchPage page) {
			if (page == null) {
				return;
			}
			IWorkbenchWindow workbenchWindow = page.getWorkbenchWindow();
			windowChanged(workbenchWindow);
		}

		@Override
		public void windowActivated(IWorkbenchWindow window) {
			windowChanged(window);
		}

		private void windowChanged(IWorkbenchWindow window) {
			if (window == null) {
				return;
			}
			Shell shell = window.getShell();
			runUpdate(shell);
		}

		@Override
		public void windowDeactivated(IWorkbenchWindow window) {
		}

		@Override
		public void windowClosed(IWorkbenchWindow window) {
		}

		@Override
		public void windowOpened(IWorkbenchWindow window) {
			hookWindow(window);
		}

		public void hookWindow(IWorkbenchWindow window) {
			if (window == null) {
				return;
			}
			window.addPageListener(this);
			window.addPerspectiveListener(this);
			IPartService partService = window.getService(IPartService.class);
			partService.addPartListener(this);
			windowChanged(window);
		}

		@Override
		public void partOpened(IWorkbenchPartReference partRef) {
			partUpdate(partRef);
		}

		@Override
		public void partActivated(IWorkbenchPartReference partRef) {
			partUpdate(partRef);
		}

		@Override
		public void partBroughtToTop(IWorkbenchPartReference partRef) {
			partUpdate(partRef);
		}

		@Override
		public void partVisible(IWorkbenchPartReference partRef) {
		}

		@Override
		public void partClosed(IWorkbenchPartReference partRef) {
			partUpdate(partRef);
		}

		@Override
		public void partDeactivated(IWorkbenchPartReference partRef) {
			partUpdate(partRef);
		}

		@Override
		public void partHidden(IWorkbenchPartReference partRef) {
			partUpdate(partRef);
		}

		@Override
		public void partInputChanged(IWorkbenchPartReference partRef) {
		}

		private void partUpdate(IWorkbenchPartReference partRef) {
			if (partRef == null) {
				return;
			}
			IWorkbenchPage page = partRef.getPage();
			pageChanged(page);
		}

		private void runUpdate(final Shell shell) {
			if (shell == null || shell.isDisposed()) {
				return;
			}
			Display display = shell.getDisplay();
			if (display == null || display.isDisposed()) {
				return;
			}
			try {
				display.asyncExec(() -> {
					if (!shell.isDisposed()) {
						installDropTarget(shell);
					}
				});
			} catch (SWTException ex) {
				if (ex.code == SWT.ERROR_DEVICE_DISPOSED) {
					//ignore
					return;
				}
				MarketplaceClientUi.error(ex);
			} catch (RuntimeException ex) {
				MarketplaceClientUi.error(ex);
			}
		}
	}
}
