/*******************************************************************************
 * Copyright (c) 2000, 2007 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.actions;
 
import java.lang.reflect.InvocationTargetException;
import java.util.*;

import org.eclipse.core.resources.*;
import org.eclipse.core.resources.mapping.*;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.team.core.RepositoryProvider;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.mapping.ISynchronizationContext;
import org.eclipse.team.core.subscribers.Subscriber;
import org.eclipse.team.core.subscribers.SubscriberScopeManager;
import org.eclipse.team.core.synchronize.SyncInfo;
import org.eclipse.team.internal.ccvs.core.*;
import org.eclipse.team.internal.ccvs.ui.*;
import org.eclipse.team.internal.ccvs.ui.mappings.WorkspaceModelParticipant;
import org.eclipse.team.internal.ccvs.ui.mappings.WorkspaceSubscriberContext;
import org.eclipse.team.internal.ccvs.ui.subscriber.WorkspaceSynchronizeParticipant;
import org.eclipse.team.internal.ui.Utils;
import org.eclipse.team.internal.ui.synchronize.actions.OpenInCompareAction;
import org.eclipse.team.ui.TeamUI;
import org.eclipse.team.ui.synchronize.*;
import org.eclipse.ui.*;

/**
 * Action to initiate a CVS workspace synchronize
 */
public class SyncAction extends WorkspaceTraversalAction {
	
	@Override
	public void execute(IAction action) throws InvocationTargetException {
		// First, see if there is a single file selected
		if (isOpenEditorForSingleFile()) {
			IFile file = getSelectedFile();
			if (file != null && isOKToShowSingleFile(file)) {
				showSingleFileComparison(getShell(), CVSProviderPlugin.getPlugin().getCVSWorkspaceSubscriber(), file, getTargetPage());
				return;
			}
		}
		if (isShowModelSync()) {
			ResourceMapping[] mappings = getCVSResourceMappings();
			if (mappings.length == 0)
				return;
			SubscriberScopeManager manager = WorkspaceSubscriberContext.createWorkspaceScopeManager(mappings, true, CommitAction.isIncludeChangeSets(getShell(), CVSUIMessages.SyncAction_1));
			WorkspaceSubscriberContext context = WorkspaceSubscriberContext.createContext(manager, ISynchronizationContext.THREE_WAY);
			WorkspaceModelParticipant participant = new WorkspaceModelParticipant(context);
			TeamUI.getSynchronizeManager().addSynchronizeParticipants(new ISynchronizeParticipant[] {participant});
			participant.run(getTargetPart());
		} else {
			IResource[] resources = getResourcesToCompare(getWorkspaceSubscriber());
			if (resources == null || resources.length == 0) return;
			// First check if there is an existing matching participant
			WorkspaceSynchronizeParticipant participant = (WorkspaceSynchronizeParticipant)SubscriberParticipant.getMatchingParticipant(WorkspaceSynchronizeParticipant.ID, resources);
			// If there isn't, create one and add to the manager
			if (participant == null) {
				ISynchronizeScope scope;
				if (includesAllCVSProjects(resources)) {
					scope = new WorkspaceScope();
				} else {
					IWorkingSet[] sets = getSelectedWorkingSets();            
					if (sets != null) {
						scope = new WorkingSetScope(sets);
					} else {
						scope = new ResourceScope(resources);
					}
				}
				participant = new WorkspaceSynchronizeParticipant(scope);
				TeamUI.getSynchronizeManager().addSynchronizeParticipants(new ISynchronizeParticipant[] {participant});
			}
			participant.refresh(resources, getTargetPart().getSite());
		}
	}

	private static boolean isShowModelSync() {
		return CVSUIPlugin.getPlugin().getPreferenceStore().getBoolean(ICVSUIConstants.PREF_ENABLE_MODEL_SYNC);
	}
	
	private static boolean isOpenEditorForSingleFile() {
		return CVSUIPlugin.getPlugin().getPreferenceStore().getBoolean(ICVSUIConstants.PREF_OPEN_COMPARE_EDITOR_FOR_SINGLE_FILE);
	}

	private IWorkingSet[] getSelectedWorkingSets() {
		ResourceMapping[] mappings = getCVSResourceMappings();
		List<IWorkingSet> sets = new ArrayList<>();
		for (int i = 0; i < mappings.length; i++) {
			ResourceMapping mapping = mappings[i];
			if (mapping.getModelObject() instanceof IWorkingSet) {
				IWorkingSet set = (IWorkingSet) mapping.getModelObject();
				sets.add(set);
			} else {
				return null;
			}
		}
		if (sets.isEmpty())
			return null;
		return sets.toArray(new IWorkingSet[sets.size()]);
	}

	private boolean includesAllCVSProjects(IResource[] resources) {
		// First, make sure all the selected thinsg are projects
		for (int i = 0; i < resources.length; i++) {
			IResource resource = resources[i];
			if (resource.getType() != IResource.PROJECT)
				return false;
		}
		IProject[] cvsProjects = getAllCVSProjects();
		return cvsProjects.length == resources.length;
	}

	private IProject[] getAllCVSProjects() {
		IProject[] projects = ResourcesPlugin.getWorkspace().getRoot().getProjects();
		Set<IProject> cvsProjects = new HashSet<>();
		for (int i = 0; i < projects.length; i++) {
			IProject project = projects[i];
			if (RepositoryProvider.isShared(project) && RepositoryProvider.getProvider(project, CVSProviderPlugin.getTypeId()) != null) {
				cvsProjects.add(project);
			}
		}
		return cvsProjects.toArray(new IProject[cvsProjects.size()]);
	}

	/**
	 * Return whether it is OK to open the selected file directly in a compare editor.
	 * It is not OK to show the single file if the file is part of a logical model element
	 * that spans files.
	 * @param file the file
	 * @return whether it is OK to open the selected file directly in a compare editor
	 */
	public static boolean isOKToShowSingleFile(IFile file) {
		if (!isShowModelSync())
			return true;
		IModelProviderDescriptor[] descriptors = ModelProvider.getModelProviderDescriptors();
		for (int i = 0; i < descriptors.length; i++) {
			IModelProviderDescriptor descriptor = descriptors[i];
			try {
				IResource[] resources = descriptor.getMatchingResources(new IResource[] { file });
				if (resources.length > 0) {
					ModelProvider provider = descriptor.getModelProvider();
					// Technically, we should us the remote context to determine if multiple resources are involved.
					// However, we do not have a progress monitor so we'll just use a local context since,
					// it is unlikely that a model element will consist of one file locally but multiple files remotely
					ResourceMapping[] mappings = provider.getMappings(file, ResourceMappingContext.LOCAL_CONTEXT, null);
					for (int j = 0; j < mappings.length; j++) {
						ResourceMapping mapping = mappings[j];
						ResourceTraversal[] traversals = mapping.getTraversals(ResourceMappingContext.LOCAL_CONTEXT, null);
						for (int k = 0; k < traversals.length; k++) {
							ResourceTraversal traversal = traversals[k];
							IResource[] tResources = traversal.getResources();
							for (int index = 0; index < tResources.length; index++) {
								IResource tr = tResources[index];
								if (!tr.equals(file))
									return false;
							}
						}
					}
				}
			} catch (CoreException e) {
				CVSUIPlugin.log(e);
			}
		}
		return true;
	}
	
	/**
	 * Refresh the subscriber directly and show the resulting synchronization state in a compare editor. If there
	 * is no difference the user is prompted.
	 * 
	 * @param resources the file to refresh and compare
	 */
	public static void showSingleFileComparison(final Shell shell, final Subscriber subscriber, final IResource resource, final IWorkbenchPage page) {
		try {
			PlatformUI.getWorkbench().getProgressService().busyCursorWhile(monitor -> {
				try {
					subscriber.refresh(new IResource[] { resource }, IResource.DEPTH_ZERO, monitor);
				} catch (TeamException e) {
					throw new InvocationTargetException(e);
				}
			});
			final SyncInfo info = subscriber.getSyncInfo(resource);
			if (info == null) return;
			shell.getDisplay().syncExec(() -> {
				if (info.getKind() == SyncInfo.IN_SYNC) {
					MessageDialog.openInformation(shell, CVSUIMessages.SyncAction_noChangesTitle,
							CVSUIMessages.SyncAction_noChangesMessage); //
				} else {
					SyncInfoCompareInput input = new SyncInfoCompareInput(subscriber.getName(), info);
					OpenInCompareAction.openCompareEditor(input, page);
				}
			});
		} catch (InvocationTargetException e) {
			Utils.handle(e);
		} catch (InterruptedException e) {
		} catch (TeamException e) {
			Utils.handle(e);
		}
	}

	public static boolean isSingleFile(IResource[] resources) {
		return resources.length == 1 && resources[0].getType() == IResource.FILE;
	}
	
	/**
	 * Enable for resources that are managed (using super) or whose parent is a
	 * CVS folder.
	 * 
	 * @see org.eclipse.team.internal.ccvs.ui.actions.WorkspaceAction#isEnabledForCVSResource(org.eclipse.team.internal.ccvs.core.ICVSResource)
	 */
	@Override
	protected boolean isEnabledForCVSResource(ICVSResource cvsResource) throws CVSException {
		return (super.isEnabledForCVSResource(cvsResource) || (cvsResource.getParent().isCVSFolder() && !cvsResource.isIgnored()));
	}
	
	@Override
	public String getId() {
		return ICVSUIConstants.CMD_SYNCHRONIZE;
	}

	
	@Override
	public boolean isEnabled() {
		if(super.isEnabled()){
			return true;
		}
		IWorkingSet[] sets = getSelectedWorkingSets();
		// empty selection will not be considered
		if(sets == null || sets.length == 0){
			return false;
		}
		
		Set projects = getProjects(sets);
		
		boolean existsProjectToSynchronize = false;
		for (Iterator it = projects.iterator(); it.hasNext();) {
			IProject project = (IProject) it.next();
			RepositoryProvider provider = RepositoryProvider.getProvider(project);
			if(provider != null){
				existsProjectToSynchronize = true;
				//we handle only CVS repositories
				if(!CVSProviderPlugin.getTypeId().equals(provider.getID())){
					return false;
				}
			}
		}
		
		return existsProjectToSynchronize;
	}

	private Set getProjects(IWorkingSet[] sets) {
		Set<IProject> projects = new HashSet<>();
		
		if(sets == null) 
			return projects;
		
		for (int i = 0; i < sets.length; i++) {
			IAdaptable ad[] = sets[i].getElements();
			if (ad != null) {
				for (int j = 0; j < ad.length; j++) {
					IResource resource = ad[j]
							.getAdapter(IResource.class);
					if (resource != null) {
						projects.add(resource.getProject());
					}
				}
			}
		}
		
		return projects;
	}
}
