/*******************************************************************************
 * Copyright (c) 2000, 2019 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.compare.internal;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;

import org.eclipse.compare.CompareConfiguration;
import org.eclipse.compare.CompareEditorInput;
import org.eclipse.compare.IPropertyChangeNotifier;
import org.eclipse.core.runtime.Adapters;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.action.IStatusLineManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.text.IFindReplaceTarget;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.IEditorActionBarContributor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorSite;
import org.eclipse.ui.IReusableEditor;
import org.eclipse.ui.ISaveablesLifecycleListener;
import org.eclipse.ui.ISaveablesSource;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchPartConstants;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.Saveable;
import org.eclipse.ui.SaveablesLifecycleEvent;
import org.eclipse.ui.actions.WorkspaceModifyOperation;
import org.eclipse.ui.contexts.IContextService;
import org.eclipse.ui.part.EditorPart;
import org.eclipse.ui.part.IShowInSource;
import org.eclipse.ui.part.PageBook;
import org.eclipse.ui.services.IServiceLocator;
import org.eclipse.ui.texteditor.ITextEditorExtension3;
import org.eclipse.ui.views.contentoutline.IContentOutlinePage;

/**
 * A CompareEditor takes a ICompareEditorInput as input.
 * Most functionality is delegated to the ICompareEditorInput.
 */
public class CompareEditor extends EditorPart
		implements IReusableEditor, ISaveablesSource, IPropertyChangeListener,
		ISaveablesLifecycleListener {
	public final static String CONFIRM_SAVE_PROPERTY= "org.eclipse.compare.internal.CONFIRM_SAVE_PROPERTY"; //$NON-NLS-1$

	private static final int UNINITIALIZED = 0;
	private static final int INITIALIZING = 1;
	private static final int NO_DIFF = 2;
	private static final int CANCELED = 3;
	private static final int INITIALIZED = 4;
	private static final int ERROR = 5;
	private static final int STILL_INITIALIZING = 6;
	private static final int CREATING_CONTROL = 7;
	private static final int DONE = 8;

	private IActionBars fActionBars;

	private PageBook fPageBook;

	/** the SWT control from the compare editor input*/
	private Control fControl;
	/** the outline page */
	private CompareOutlinePage fOutlinePage;

	private CompareSaveable fSaveable;

	private Control initializingPage;
	private Control emptyPage;

	private int state = UNINITIALIZED;
	private HashSet<Saveable> knownSaveables;

	private final EditorCompareContainer fContainer = new EditorCompareContainer();

	private class EditorCompareContainer extends CompareContainer {
		@Override
		public void registerContextMenu(MenuManager menu, ISelectionProvider provider) {
			if (getSite() instanceof IEditorSite) {
				IEditorSite es = (IEditorSite) getSite();
				es.registerContextMenu(menu, provider, true);
			}
		}

		@Override
		public void setStatusMessage(String message) {
			if (fActionBars != null) {
				IStatusLineManager slm= fActionBars.getStatusLineManager();
				if (slm != null) {
					slm.setMessage(message);
				}
			}
		}

		@Override
		public IServiceLocator getServiceLocator() {
			return getSite();
		}

		@Override
		protected WorkerJob createWorkerJob() {
			WorkerJob workerJob = new WorkerJob(getWorkerJobName()) {
				@Override
				public boolean belongsTo(Object family) {
					if (family == CompareEditor.this)
						return true;
					return super.belongsTo(family);
				}
			};
			return workerJob;
		}

		@Override
		protected String getWorkerJobName() {
			return NLS.bind(CompareMessages.CompareEditor_2, getTitle());
		}

		@Override
		public IWorkbenchPart getWorkbenchPart() {
			return CompareEditor.this;
		}

		@Override
		public IActionBars getActionBars() {
			return CompareEditor.this.getActionBars();
		}
	}

	/**
	 * No-argument constructor required for extension points.
	 */
	public CompareEditor() {
		// empty default implementation
	}

	@Override
	@SuppressWarnings("unchecked")
	public <T> T getAdapter(Class<T> key) {
		if (key.equals(IContentOutlinePage.class)) {
			Object object= getCompareConfiguration().getProperty(CompareConfiguration.USE_OUTLINE_VIEW);
			if (object instanceof Boolean && ((Boolean)object).booleanValue()) {
				if (fOutlinePage != null) {
					if (fOutlinePage.getControl() != null && fOutlinePage.getControl().isDisposed()) {
						fOutlinePage = null;
					} else {
						return (T) fOutlinePage;
					}
				}
				fOutlinePage= new CompareOutlinePage(this);
				return (T) fOutlinePage;
			}
		}

		if (key == IShowInSource.class
				|| key == OutlineViewerCreator.class
				|| key == IFindReplaceTarget.class) {
			Object input = getEditorInput();
			if (input != null) {
				return Adapters.adapt(input, key);
			}
		}

		if (key == IEditorInput.class) {
			// return (T) Adapters.adapt(getEditorInput(), IEditorInput.class);
			// The above call cannot be used because the return type of getEditorInput()
			// call is IEditorInput and this itself will be returned by the above function.
			// What we want is to call getAdapter call on this IEditorInput object.
			return (T) getEditorInput().getAdapter(IEditorInput.class);
		}

		if (key == ITextEditorExtension3.class) {
			return (T) Adapters.adapt(getEditorInput(), ITextEditorExtension3.class);
		}

		return super.getAdapter(key);
	}

	/*
	 * Helper method used by ComapreEditorConfiguration to get at the compare configuration of the editor
	 */
	CompareConfiguration getCompareConfiguration() {
		IEditorInput input= getEditorInput();
		if (input instanceof CompareEditorInput)
			return ((CompareEditorInput)input).getCompareConfiguration();
		return null;
	}

	@Override
	public void init(IEditorSite site, IEditorInput input) throws PartInitException {
		if (!(input instanceof CompareEditorInput))
			throw new PartInitException(Utilities.getString("CompareEditor.invalidInput")); //$NON-NLS-1$

		setSite(site);
		setInput(input);
	}

	@Override
	public void setInput(IEditorInput input) {
		if (!(input instanceof CompareEditorInput)) {
			IStatus s= new Status(IStatus.ERROR, PlatformUI.PLUGIN_ID, IStatus.OK, Utilities.getString("CompareEditor.invalidInput"), null); //$NON-NLS-1$
			String title= Utilities.getString("CompareEditor.error.setinput.title"); //$NON-NLS-1$
			String msg= Utilities.getString("CompareEditor.error.setinput.message"); //$NON-NLS-1$
			ErrorDialog.openError(getSite().getShell(), title, msg, s);
			return;
		}
		doSetInput(input);
		// Need to refresh the contributor (see #67888)
		refreshActionBarsContributor();
	}

	public void refreshActionBarsContributor() {
		IEditorSite editorSite= getEditorSite();
		if (editorSite != null) {
			IEditorActionBarContributor actionBarContributor= editorSite.getActionBarContributor();
			if (actionBarContributor != null) {
					actionBarContributor.setActiveEditor(null);
					actionBarContributor.setActiveEditor(this);
			}
		}
	}

	private void doSetInput(IEditorInput input) {
		IEditorInput oldInput= getEditorInput();
		disconnectFromInput(oldInput);
		Point oldSize = null;
		boolean hadPreviousInput = oldInput != null;
		if (hadPreviousInput) {
			// Cancel any jobs associated with the old input
			Job.getJobManager().cancel(this);
			if (fControl != null && !fControl.isDisposed()) {
				oldSize= fControl.getSize();
				if (emptyPage == null)
					emptyPage = new Composite(fPageBook, SWT.NONE);
				fPageBook.showPage(emptyPage);
				fControl.dispose();
				fControl = null;
			}
		}

		super.setInput(input);

		if (fOutlinePage != null)
			fOutlinePage.reset();

		final CompareEditorInput cei= (CompareEditorInput) input;
		cei.setContainer(fContainer);
		setTitleImage(cei.getTitleImage());
		setPartName(cei.getTitle());
		setTitleToolTip(cei.getToolTipText());

		if (input instanceof IPropertyChangeNotifier)
			((IPropertyChangeNotifier)input).addPropertyChangeListener(this);

		setState(cei.getCompareResult() == null ? INITIALIZING : INITIALIZED);
		if (fPageBook != null)
			createCompareControl();
		if (fControl != null && oldSize != null)
			fControl.setSize(oldSize);

		boolean hasResult = cei.getCompareResult() != null;
		if (!hasResult) {
			initializeInBackground(cei, hadPreviousInput);
		}

		firePropertyChange(IWorkbenchPartConstants.PROP_INPUT);

		// We only need to notify of new Saveables if we are changing inputs
		if (hadPreviousInput && hasResult) {
			registerSaveable();
		}
	}

	private void registerSaveable() {
		ISaveablesLifecycleListener lifecycleListener= getSite().getService(ISaveablesLifecycleListener.class);
		lifecycleListener.handleLifecycleEvent(
			new SaveablesLifecycleEvent(this, SaveablesLifecycleEvent.POST_OPEN, internalGetSaveables(true), false));
	}

	private void disconnectFromInput(IEditorInput oldInput) {
		if (oldInput != null) {
			if (oldInput instanceof IPropertyChangeNotifier)
				((IPropertyChangeNotifier)oldInput).removePropertyChangeListener(this);

			// Let the workbench know that the old input's saveables are no longer needed
			if (knownSaveables != null && !knownSaveables.isEmpty()) {
				ISaveablesLifecycleListener lifecycleListener= getSite().getService(ISaveablesLifecycleListener.class);
				lifecycleListener.handleLifecycleEvent(
						new SaveablesLifecycleEvent(this, SaveablesLifecycleEvent.POST_CLOSE, knownSaveables.toArray(new Saveable[knownSaveables.size()]), false));
				knownSaveables.clear();
			}
		}
	}

	protected void initializeInBackground(final CompareEditorInput cei, final boolean hadPreviousInput) {
		// Need to cancel any running jobs associated with the oldInput
		Job job = new Job(NLS.bind(CompareMessages.CompareEditor_0, cei.getTitle())) {
			@Override
			protected IStatus run(final IProgressMonitor monitor) {
				final int[] newState = new int[] { ERROR };
				try {
					IStatus status = CompareUIPlugin.getDefault().prepareInput(cei, monitor);
					if (status.isOK()) {
						// We need to update the saveables list
						newState[0] = INITIALIZED;
						return Status.OK_STATUS;
					}
					if (status.getCode() == CompareUIPlugin.NO_DIFFERENCE) {
						newState[0] = NO_DIFF;
						return Status.OK_STATUS;
					}
					newState[0] = ERROR;
					return status;
				} catch (OperationCanceledException e) {
					newState[0] = CANCELED;
					return Status.CANCEL_STATUS;
				} finally {
					if (monitor.isCanceled())
						newState[0] = CANCELED;
					Display.getDefault().syncExec(() -> {
						if (fPageBook.isDisposed())
							return;
						// we need to register the saveable if we had a previous input or if
						// there are knownSaveables (which means that the workbench called
						// getSaveables and got an empty list
						if (hadPreviousInput || (knownSaveables != null && !isAllSaveablesKnown())) {
							registerSaveable();
						}
						setState(newState[0]);
						createCompareControl();
					});
					monitor.done();
				}
			}
			@Override
			public boolean belongsTo(Object family) {
				if (family == CompareEditor.this || family == cei)
					return true;
				return cei.belongsTo(family);
			}
		};
		job.setUser(true);
		Utilities.schedule(job, getSite());
	}

	/*
	 * Helper method used to find an action bars using the Utilities#findActionsBars(Control)
	 */
	public IActionBars getActionBars() {
		return fActionBars;
	}

	/**
	 * Sets the action bars so the Utilities class can access it.
	 */
	void setActionBars(IActionBars actionBars) {
		fActionBars= actionBars;
	}

	@Override
	public void createPartControl(Composite parent) {
		parent.setData(this);
		fPageBook = new PageBook(parent, SWT.NONE);
		createCompareControl();
		IContextService service = getSite().getService(IContextService.class);
		if (service != null) {
			service.activateContext("org.eclipse.compare.compareEditorScope"); //$NON-NLS-1$
			service.activateContext("org.eclipse.ui.textEditorScope"); //$NON-NLS-1$
		}
	}

	private void createCompareControl() {
		if (fPageBook.isDisposed())
			return;
		IEditorInput input= getEditorInput();
		if (input instanceof CompareEditorInput) {
			CompareEditorInput ci = (CompareEditorInput) input;
			if (ci.getCompareResult() == null) {
				if (getState() == INITIALIZING) {
					getSite().setSelectionProvider(new CompareEditorSelectionProvider());
					setPageLater();
				} else if (getState() == STILL_INITIALIZING) {
					if (initializingPage == null) {
						initializingPage = getInitializingMessagePane(fPageBook);
					}
					fPageBook.showPage(initializingPage);
				} else if (getState() == CANCELED) {
					// Close the editor when we are canceled
					closeEditor();
				} else if (getState() == NO_DIFF) {
					// Prompt and close the editor as well
					setState(DONE);
					closeEditor();
					CompareUIPlugin.getDefault().handleNoDifference();
				} else if (getState() == ERROR) {
					// If an error occurred, close the editor
					// (the message would be displayed by the progress view)
					closeEditor();
				}
			} else if (fControl == null && getState() != CREATING_CONTROL) {
				if (getState() == CANCELED) {
					// Close the editor when we are canceled, even when compare
					// result has been already prepared
					closeEditor();
					return;
				}
				// Set the state in case this method gets called again
				setState(CREATING_CONTROL);
				if (getSite().getSelectionProvider() == null)
					getSite().setSelectionProvider(new CompareEditorSelectionProvider());
				try {
					fControl = ci.createContents(fPageBook);
				} catch (SWTException e) {
					// closed while creating
					if (e.code == SWT.ERROR_WIDGET_DISPOSED) {
						setState(CANCELED);
						return;
					}
				}
				fPageBook.showPage(fControl);
				PlatformUI.getWorkbench().getHelpSystem().setHelp(fControl, ICompareContextIds.COMPARE_EDITOR);
				if (isActive()) {
					setFocus();
				}
				setState(INITIALIZED);
			}
		}
	}

	private boolean isActive() {
		return getSite().getPage().getActivePart() == this;
	}

	private void setPageLater() {
		Display.getCurrent().timerExec(1000, () -> {
			synchronized(CompareEditor.this) {
				if (getState() == INITIALIZING) {
					setState(STILL_INITIALIZING);
					createCompareControl();
				}
			}
		});
	}

	@Override
	public void dispose() {
		IEditorInput input= getEditorInput();
		if (input instanceof IPropertyChangeNotifier)
			((IPropertyChangeNotifier)input).removePropertyChangeListener(this);
		super.dispose();
	}

	@Override
	public void setFocus() {
		IEditorInput input= getEditorInput();
		if (input instanceof CompareEditorInput)
			if (!((CompareEditorInput)input).setFocus2())
				fPageBook.setFocus();
	}

	@Override
	public boolean isSaveAsAllowed() {
		return false;
	}

	@Override
	public void doSaveAs() {
		Assert.isTrue(false); // Save As not supported for CompareEditor
	}

	@Override
	public void doSave(IProgressMonitor progressMonitor) {
		final IEditorInput input= getEditorInput();

		WorkspaceModifyOperation operation= new WorkspaceModifyOperation() {
			@Override
			public void execute(IProgressMonitor pm) throws CoreException {
				if (input instanceof CompareEditorInput)
					((CompareEditorInput)input).saveChanges(pm);
			}
		};

		Shell shell= getSite().getShell();

		try {
			operation.run(progressMonitor);
			firePropertyChange(PROP_DIRTY);
		} catch (InterruptedException | OperationCanceledException x) {
			// NeedWork
		} catch (InvocationTargetException x) {
			String title= Utilities.getString("CompareEditor.saveError.title"); //$NON-NLS-1$
			String reason= x.getTargetException().getMessage();
			MessageDialog.openError(shell, title, Utilities.getFormattedString("CompareEditor.cantSaveError", reason));	//$NON-NLS-1$
		}
	}

	@Override
	public boolean isDirty() {
		IEditorInput input= getEditorInput();
		if (input instanceof CompareEditorInput)
			return ((CompareEditorInput)input).isDirty();
		return false;
	}

	@Override
	public void propertyChange(PropertyChangeEvent event) {
		if (event.getProperty().equals(CompareEditorInput.DIRTY_STATE)) {
			Object old_value= event.getOldValue();
			Object new_value= event.getNewValue();
			if (old_value == null || new_value == null || !old_value.equals(new_value))
				firePropertyChange(PROP_DIRTY);
		} else if (event.getProperty().equals(CompareEditorInput.PROP_TITLE)) {
			setPartName(((CompareEditorInput)getEditorInput()).getTitle());
			setTitleToolTip(((CompareEditorInput)getEditorInput()).getToolTipText());
		} else if (event.getProperty().equals(CompareEditorInput.PROP_TITLE_IMAGE)) {
			setTitleImage(((CompareEditorInput)getEditorInput()).getTitleImage());
		}
	}

	@Override
	public Saveable[] getSaveables() {
		return internalGetSaveables(knownSaveables == null);
	}

	private Saveable[] internalGetSaveables(boolean init) {
		IEditorInput input= getEditorInput();
		Saveable[] sourceSaveables = getSaveables(input);
		if (init || knownSaveables == null) {
			recordSaveables(sourceSaveables);
		} else {
			for (Saveable saveable : sourceSaveables) {
				if (!knownSaveables.contains(saveable)) {
					CompareUIPlugin.logErrorMessage(NLS.bind("Saveable {0} was not added using a saveables lifecycle event.", saveable.getName())); //$NON-NLS-1$
					knownSaveables.add(saveable);
				}
			}
			if (sourceSaveables.length != knownSaveables.size()) {
				CompareUIPlugin.logErrorMessage("Saveables were removed without an appropriate event"); //$NON-NLS-1$
				knownSaveables.clear();
				recordSaveables(sourceSaveables);
			}
		}
		return sourceSaveables;
	}

	private boolean isAllSaveablesKnown() {
		IEditorInput input= getEditorInput();
		Saveable[] sourceSaveables = getSaveables(input);
		if (knownSaveables == null) {
			return sourceSaveables.length == 0;
		}
		if (sourceSaveables.length != knownSaveables.size()) {
			return false;
		}
		for (Saveable saveable : sourceSaveables) {
			if (!knownSaveables.contains(saveable)) {
				return false;
			}
		}
		return true;
	}

	private void recordSaveables(Saveable[] sourceSaveables) {
		if (knownSaveables == null)
			knownSaveables = new HashSet<>();
		Collections.addAll(knownSaveables, sourceSaveables);
	}

	private Saveable[] getSaveables(IEditorInput input) {
		if (input instanceof ISaveablesSource) {
			ISaveablesSource source= (ISaveablesSource) input;
			return source.getSaveables();
		}
		return new Saveable[] { getSaveable() };
	}

	private Saveable getSaveable() {
		if (fSaveable == null) {
			fSaveable= new CompareSaveable();
		}
		return fSaveable;
	}

	@Override
	public Saveable[] getActiveSaveables() {
		IEditorInput input= getEditorInput();
		if (input instanceof ISaveablesSource) {
			ISaveablesSource source= (ISaveablesSource) input;
			return source.getActiveSaveables();
		}
		return new Saveable[] { getSaveable() };
	}

	private class CompareSaveable extends Saveable {

		@Override
		public String getName() {
			return CompareEditor.this.getPartName();
		}

		@Override
		public String getToolTipText() {
			return CompareEditor.this.getTitleToolTip();
		}

		@Override
		public ImageDescriptor getImageDescriptor() {
			return ImageDescriptor.createFromImage(CompareEditor.this.getTitleImage());
		}

		@Override
		public void doSave(IProgressMonitor monitor) throws CoreException {
			CompareEditor.this.doSave(monitor);
		}

		@Override
		public boolean isDirty() {
			return CompareEditor.this.isDirty();
		}

		@Override
		public boolean equals(Object object) {
			return object == this;
		}

		@Override
		public int hashCode() {
			return CompareEditor.this.hashCode();
		}
	}

	private Composite getInitializingMessagePane(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);
		composite.setBackground(getBackgroundColor(parent));
		GridLayout layout = new GridLayout();
		layout.numColumns = 3;
		composite.setLayout(layout);

		createDescriptionLabel(composite, CompareMessages.CompareEditor_1);
		return composite;
	}

	private Color getBackgroundColor(Composite parent) {
		return parent.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
	}

	private Label createDescriptionLabel(Composite parent, String text) {
		Label description = new Label(parent, SWT.WRAP);
		GridData data = new GridData(GridData.FILL_HORIZONTAL);
		data.horizontalSpan = 2;
		description.setLayoutData(data);
		description.setText(text);
		description.setBackground(getBackgroundColor(parent));
		return description;
	}

	private void closeEditor() {
		getSite().getPage().closeEditor(CompareEditor.this, false);
	}

	private synchronized void setState(int state) {
		this.state = state;
	}

	private int getState() {
		return state;
	}

	@Override
	public void handleLifecycleEvent(SaveablesLifecycleEvent event) {
		ISaveablesLifecycleListener lifecycleListener=
				getSite().getService(ISaveablesLifecycleListener.class);
		if (event.getEventType() == SaveablesLifecycleEvent.POST_CLOSE) {
			// We may get a post close for a saveable that is not known to the workbench.
			// Only pass on the event for known saveables
			if (knownSaveables == null || knownSaveables.isEmpty())
				return;
			java.util.List<Saveable> result = new ArrayList<>();
			Saveable[] all = event.getSaveables();
			for (Saveable saveable : all) {
				if (knownSaveables.contains(saveable))
					result.add(saveable);
				knownSaveables.remove(saveable);
			}
			if (result.isEmpty())
				return;
			event = new SaveablesLifecycleEvent(this,
					SaveablesLifecycleEvent.POST_CLOSE,
					result.toArray(new Saveable[result.size()]),
					false);
		} else if (event.getEventType() == SaveablesLifecycleEvent.POST_OPEN) {
			recordSaveables(event.getSaveables());
		}
		lifecycleListener.handleLifecycleEvent(event);
	}
}
