/*******************************************************************************
 * Copyright (c) 2000, 2008 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.team.internal.ccvs.ui;

import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.HashSet;
import java.util.Set;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.team.FileModificationValidationContext;
import org.eclipse.core.runtime.*;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.Job;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.synchronize.SyncInfo;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.core.client.Command;
import org.eclipse.team.internal.ccvs.ui.actions.EditorsAction;
import org.eclipse.team.internal.ccvs.ui.operations.UpdateOperation;
import org.eclipse.team.internal.ui.Utils;
import org.eclipse.ui.progress.IProgressConstants;

/**
 * IFileModificationValidator that is plugged into the CVS Repository Provider
 */
public class FileModificationValidator extends CVSCoreFileModificationValidator {
	
	public FileModificationValidator() {
	}
	
	@Override
	protected IStatus edit(IFile[] readOnlyFiles, FileModificationValidationContext context) {
		return edit(readOnlyFiles, getShell(context));
	}
	
	private Shell getShell(FileModificationValidationContext context) {
		if (context == null)
			return null;
		if (context.getShell() != null)
			return (Shell)context.getShell();
		return Utils.getShell(null, true);
	}

	private IStatus getStatus(InvocationTargetException e) {
		Throwable target = e.getTargetException();
		if (target instanceof TeamException) {
			return ((TeamException) target).getStatus();
		} else if (target instanceof CoreException) {
			return ((CoreException) target).getStatus();
		}
		return new Status(IStatus.ERROR, CVSUIPlugin.ID, 0, CVSUIMessages.internal, target); 
	}
		
	private IStatus edit(final IFile[] files, final Shell shell) {
		if (isPerformEdit()) {
			try {
				if (shell != null && !promptToEditFiles(files, shell)) {
					// The user didn't want to edit.
					// OK is returned but the file remains read-only
					throw new InterruptedException();
				}
				
				// see if the file is up to date
				if (shell != null && promptToUpdateFiles(files, shell)) {
					// The user wants to update the file
					// Run the update in a runnable in order to get a busy cursor.
					// This runnable is syncExeced in order to get a busy cursor
					IRunnableWithProgress updateRunnable = monitor -> performUpdate(files, monitor);
					if (isRunningInUIThread()) {
						// Only show a busy cursor if validate edit is blocking the UI
						CVSUIPlugin.runWithProgress(shell, false, updateRunnable);
					} else {
						// We can't show a busy cursor (i.e., run in the UI thread)
						// since this thread may hold locks and
						// running an edit in the UI thread could try to obtain the
						// same locks, resulting in a deadlock.
						updateRunnable.run(new NullProgressMonitor());
					}
				}
				
				// Run the edit in a runnable in order to get a busy cursor.
				// This runnable is syncExeced in order to get a busy cursor
				IRunnableWithProgress editRunnable = monitor -> {
					try {
						performEdit(files, monitor);
					} catch (CVSException e) {
						throw new InvocationTargetException(e);
					}
				};
				if (isRunningInUIThread()) {
					// Only show a busy cursor if validate edit is blocking the UI
					CVSUIPlugin.runWithProgress(shell, false, editRunnable);
				} else {
					// We can't show a busy cursor (i.e., run in the UI thread)
					// since this thread may hold locks and
					// running an edit in the UI thread could try to obtain the
					// same locks, resulting in a deadlock.
					editRunnable.run(new NullProgressMonitor());
				}
			} catch (InvocationTargetException e) {
				return getStatus(e);
			} catch (InterruptedException e) {
				// Must return an error to indicate that it is not OK to edit the files
				return new Status(IStatus.CANCEL, CVSUIPlugin.ID, 0, CVSUIMessages.FileModificationValidator_vetoMessage, null); //;
			}
		} else if (isPerformEditInBackground()) {
			IStatus status = setWritable(files);
			if (status.isOK())
				performEdit(files);
			return status;
		} else {
			// Allow the files to be edited without notifying the server
			return setWritable(files);
		}

		return Status.OK_STATUS;
		
	}
	
	@Override
	protected void scheduleEditJob(Job job) {
		job.setProperty(IProgressConstants.NO_IMMEDIATE_ERROR_PROMPT_PROPERTY, Boolean.TRUE);
		job.setProperty(IProgressConstants.ICON_PROPERTY, getOperationIcon());
		super.scheduleEditJob(job);
	}
	
	private URL getOperationIcon() {
		return FileLocator.find(CVSUIPlugin.getPlugin().getBundle(), new Path(ICVSUIConstants.ICON_PATH + ICVSUIConstants.IMG_CVS_PERSPECTIVE), null);
	}
	
	private boolean isRunningInUIThread() {
		return Display.getCurrent() != null;
	}

	private boolean promptToEditFiles(IFile[] files, Shell shell) throws InvocationTargetException, InterruptedException {
		if (files.length == 0)
			return true;		

		if(isNeverPrompt())	
			return true;

		// Contact the server to see if anyone else is editing the files
		EditorsAction editors = fetchEditors(files, shell);
		if (editors.isEmpty()) {
			if (isAlwaysPrompt()) 
				return (promptEdit(shell));
			return true;
		} else {
			return (editors.promptToEdit(shell));
		}
	}
	
	private boolean promptToUpdateFiles(IFile[] files, Shell shell) throws InvocationTargetException, InterruptedException {
		if (files.length == 0)
			return false;
		
		if (isNeverUpdate())
			return false;
		
		// Contact the server to see if the files are up-to-date
		if (needsUpdate(files, new NullProgressMonitor())) {
			if (isPromptUpdate())
				return (promptUpdate(shell));
			return true; // auto update
		}
		
		return false;
	}

	private boolean promptEdit(Shell shell) {
		// Open the dialog using a sync exec (there are no guarantees that we
		// were called from the UI thread
		final boolean[] result = new boolean[] { false };
		int flags = isRunningInUIThread() ? 0 : CVSUIPlugin.PERFORM_SYNC_EXEC;
		CVSUIPlugin
				.openDialog(shell,
						shell1 -> result[0] = MessageDialog.openQuestion(shell1,
								CVSUIMessages.FileModificationValidator_3, CVSUIMessages.FileModificationValidator_4),
						flags);
		return result[0];
	}

	private boolean promptUpdate(Shell shell) {
		// Open the dialog using a sync exec (there are no guarantees that we
		// were called from the UI thread
		final boolean[] result = new boolean[] { false };
		int flags = isRunningInUIThread() ? 0 : CVSUIPlugin.PERFORM_SYNC_EXEC;
		CVSUIPlugin
				.openDialog(shell,
						shell1 -> result[0] = MessageDialog.openQuestion(shell1,
								CVSUIMessages.FileModificationValidator_5, CVSUIMessages.FileModificationValidator_6),
						flags);
		return result[0];
	}

	private boolean isPerformEdit() {
		return ICVSUIConstants.PREF_EDIT_PROMPT_EDIT.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_EDIT_ACTION));
	}
	
	private boolean isPerformEditInBackground() {
		return ICVSUIConstants.PREF_EDIT_IN_BACKGROUND.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_EDIT_ACTION));
	}
	
	private EditorsAction fetchEditors(IFile[] files, Shell shell) throws InvocationTargetException, InterruptedException {
		final EditorsAction editors = new EditorsAction(getProvider(files), files);
		IRunnableWithProgress runnable = monitor -> editors.run(monitor);
		if (isRunningInUIThread()) {
			// Show a busy cursor if we are running in the UI thread
			CVSUIPlugin.runWithProgress(shell, false, runnable);
		} else {
			// We can't show a busy cursor (i.e., run in the UI thread)
			// since this thread may hold locks and
			// running a CVS operation in the UI thread could try to obtain the
			// same locks, resulting in a deadlock.
			runnable.run(new NullProgressMonitor());
		}
		return editors;
	}

	private boolean isNeverPrompt() {
		return ICVSUIConstants.PREF_EDIT_PROMPT_NEVER.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_EDIT_PROMPT));
	}

	private boolean isAlwaysPrompt() {
		return ICVSUIConstants.PREF_EDIT_PROMPT_ALWAYS.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_EDIT_PROMPT));
	}
	
	private boolean needsUpdate(IFile[] files, IProgressMonitor monitor) {
		try {
			CVSWorkspaceSubscriber subscriber = CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber();
			subscriber.refresh(files, IResource.DEPTH_ZERO, monitor);
			for (int i = 0; i < files.length; i++) {
				IFile file = files[i];
				SyncInfo info = subscriber.getSyncInfo(file);
				int direction = info.getKind() & SyncInfo.DIRECTION_MASK;
				if (direction == SyncInfo.CONFLICTING || direction == SyncInfo.INCOMING) {
					return true;
				}
			}
		} catch (TeamException e) {
			// Log the exception and assume we don't need to update it
			CVSProviderPlugin.log(e);
		}
		return false;
	}
	
	private void performUpdate(IFile[] files, IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
		// TODO: This obtains the project rule which can cause a rule violation
		new UpdateOperation(null /* no target part */, files, Command.NO_LOCAL_OPTIONS, null /* no tag */).run(monitor);
	}
	
	private boolean isPromptUpdate() {
		return ICVSUIConstants.PREF_UPDATE_PROMPT_IF_OUTDATED.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_UPDATE_PROMPT));
	}
	
	private boolean isNeverUpdate() {
		return ICVSUIConstants.PREF_UPDATE_PROMPT_NEVER.equals(CVSUIPlugin.getPlugin().getPreferenceStore().getString(ICVSUIConstants.PREF_UPDATE_PROMPT));
	}
	
	@Override
	public ISchedulingRule validateEditRule(CVSResourceRuleFactory factory, IResource[] resources) {
		if (!isNeverUpdate()) {
			// We may need to perform an update so we need to obtain the lock on each project
			Set projects = new HashSet();
			for (int i = 0; i < resources.length; i++) {
				IResource resource = resources[i];
				if (isReadOnly(resource))
					projects.add(resource.getProject());
			}
			return createSchedulingRule(projects);
		}
		return internalValidateEditRule(factory, resources);
	}
}
