/*******************************************************************************
 * Copyright (c) 2000, 2017 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.ui.synchronize;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.team.core.TeamException;
import org.eclipse.team.core.diff.IDiff;
import org.eclipse.team.core.diff.IDiffChangeEvent;
import org.eclipse.team.core.diff.IDiffChangeListener;
import org.eclipse.team.core.diff.IDiffTree;
import org.eclipse.team.core.mapping.IResourceDiffTree;
import org.eclipse.team.core.mapping.provider.ResourceDiffTree;
import org.eclipse.team.core.synchronize.ISyncInfoSetChangeEvent;
import org.eclipse.team.core.synchronize.SyncInfo;
import org.eclipse.team.core.synchronize.SyncInfoSet;
import org.eclipse.team.core.synchronize.SyncInfoTree;
import org.eclipse.team.internal.core.subscribers.ActiveChangeSetManager;
import org.eclipse.team.internal.core.subscribers.ChangeSet;
import org.eclipse.team.internal.core.subscribers.DiffChangeSet;
import org.eclipse.team.internal.core.subscribers.IChangeSetChangeListener;
import org.eclipse.team.internal.core.subscribers.SubscriberChangeSetManager;
import org.eclipse.team.internal.ui.TeamUIPlugin;
import org.eclipse.team.ui.synchronize.ISynchronizePageConfiguration;
import org.eclipse.team.ui.synchronize.ISynchronizeParticipant;
import org.eclipse.team.ui.synchronize.SubscriberParticipant;

/**
 * Group incoming changes according to the active change set that are
 * located in
 */
public class ActiveChangeSetCollector implements IDiffChangeListener {

	private final ISynchronizePageConfiguration configuration;

	/*
	 * Map active change sets to infos displayed by the participant
	 */
	private final Map<ChangeSet, SyncInfoSet> activeSets = new HashMap<>();

	/*
	 * Set which contains those changes that are not part of an active set
	 */
	private SyncInfoTree rootSet = new SyncInfoTree();

	private final ChangeSetModelProvider provider;

	/*
	 * Listener registered with active change set manager
	 */
	private IChangeSetChangeListener activeChangeSetListener = new IChangeSetChangeListener() {

		@Override
		public void setAdded(final ChangeSet set) {
			// Remove any resources that are in the new set
			provider.performUpdate(monitor -> {
				remove(set.getResources());
				createSyncInfoSet(set);
			}, true, true);
		}

		@Override
		public void defaultSetChanged(final ChangeSet previousDefault, final ChangeSet set) {
			provider.performUpdate(monitor -> {
				if (listener != null)
					listener.defaultSetChanged(previousDefault, set);
			}, true, true);
		}

		@Override
		public void setRemoved(final ChangeSet set) {
			provider.performUpdate(monitor -> {
				remove(set);
				if (!set.isEmpty()) {
					add(getSyncInfos(set).getSyncInfos());
				}
			}, true, true);
		}

		@Override
		public void nameChanged(final ChangeSet set) {
			provider.performUpdate(monitor -> {
				if (listener != null)
					listener.nameChanged(set);
			}, true, true);
		}

		@Override
		public void resourcesChanged(final ChangeSet set, final IPath[] paths) {
			// Look for any resources that were removed from the set but are still out-of sync.
			// Re-add those resources
			final List<SyncInfo> outOfSync = new ArrayList<>();
			for (int i = 0; i < paths.length; i++) {
				IPath path = paths[i];
				if (!((DiffChangeSet)set).contains(path)) {
					SyncInfo info = getSyncInfo(path);
					if (info != null && info.getKind() != SyncInfo.IN_SYNC) {
						outOfSync.add(info);
					}
				}
			}
			if (!outOfSync.isEmpty()) {
				provider.performUpdate(monitor -> add(outOfSync.toArray(new SyncInfo[outOfSync.size()])), true, true);
			}
		}
	};

	/**
	 * Listener that wants to receive change events from this collector
	 */
	private IChangeSetChangeListener listener;

	public ActiveChangeSetCollector(ISynchronizePageConfiguration configuration, ChangeSetModelProvider provider) {
		this.configuration = configuration;
		this.provider = provider;
		getActiveChangeSetManager().addListener(activeChangeSetListener);
	}

	public ISynchronizePageConfiguration getConfiguration() {
		return configuration;
	}

	public ActiveChangeSetManager getActiveChangeSetManager() {
		ISynchronizeParticipant participant = getConfiguration().getParticipant();
		if (participant instanceof IChangeSetProvider) {
			return ((IChangeSetProvider)participant).getChangeSetCapability().getActiveChangeSetManager();
		}
		return null;
	}

	/**
	 * Re-populate the change sets from the seed set.
	 * If <code>null</code> is passed, the state
	 * of the collector is cleared but the set is not
	 * re-populated.
	 * <p>
	 * This method is invoked by the model provider when the
	 * model provider changes state. It should not
	 * be invoked by other clients. The model provider
	 * will invoke this method from a particular thread (which may
	 * or may not be the UI thread). Updates done to the collector
	 * from within this thread will be thread-safe and update the view
	 * properly. Updates done from other threads should use the
	 * <code>performUpdate</code> method to ensure the view is
	 * updated properly.
	 * @param seedSet
	 */
	public void reset(SyncInfoSet seedSet) {
		// First, clean up
		rootSet.clear();
		ChangeSet[] sets = activeSets.keySet().toArray(new ChangeSet[activeSets.size()]);
		for (int i = 0; i < sets.length; i++) {
			ChangeSet set = sets[i];
			remove(set);
		}
		activeSets.clear();

		// Now re-populate
		if (seedSet != null) {
			if (getConfiguration().getComparisonType() == ISynchronizePageConfiguration.THREE_WAY) {
				// Show all active change sets even if they are empty
				sets = getActiveChangeSetManager().getSets();
				for (int i = 0; i < sets.length; i++) {
					ChangeSet set = sets[i];
					add(set);
				}
				// The above will add all sync info that are contained in sets.
				// We still need to add uncontained infos to the root set
				SyncInfo[] syncInfos = seedSet.getSyncInfos();
				for (int i = 0; i < syncInfos.length; i++) {
					SyncInfo info = syncInfos[i];
					if (isLocalChange(info)) {
						ChangeSet[] containingSets = findChangeSets(info);
						if (containingSets.length == 0) {
							rootSet.add(info);
						}
					}
				}
			} else {
				add(seedSet.getSyncInfos());
			}
		}
	}

	/**
	 * Handle a sync info set change event from the provider's
	 * seed set.
	 * <p>
	 * This method is invoked by the model provider when the
	 * model provider changes state. It should not
	 * be invoked by other clients. The model provider
	 * will invoke this method from a particular thread (which may
	 * or may not be the UI thread). Updates done to the collector
	 * from within this thread will be thread-safe and update the view
	 * properly. Updates done from other threads should use the
	 * <code>performUpdate</code> method to ensure the view is
	 * updated properly.
	 */
	public void handleChange(ISyncInfoSetChangeEvent event) {
		List<IResource> removals = new ArrayList<>();
		List<SyncInfo> additions = new ArrayList<>();
		removals.addAll(Arrays.asList(event.getRemovedResources()));
		additions.addAll(Arrays.asList(event.getAddedResources()));
		SyncInfo[] changed = event.getChangedResources();
		for (int i = 0; i < changed.length; i++) {
			SyncInfo info = changed[i];
			additions.add(info);
			removals.add(info.getLocal());
		}
		if (!removals.isEmpty()) {
			remove(removals.toArray(new IResource[removals.size()]));
		}
		if (!additions.isEmpty()) {
			add(additions.toArray(new SyncInfo[additions.size()]));
		}
	}

	/**
	 * Remove the given resources from all sets of this collector.
	 * @param resources the resources to be removed
	 */
	protected void remove(IResource[] resources) {
		for (Iterator iter = activeSets.values().iterator(); iter.hasNext();) {
			SyncInfoSet set = (SyncInfoSet) iter.next();
			set.removeAll(resources);
		}
		rootSet.removeAll(resources);
	}

	protected void add(SyncInfo[] infos) {
		rootSet.beginInput();
		for (int i = 0; i < infos.length; i++) {
			SyncInfo info = infos[i];
			if (isLocalChange(info) && select(info)) {
				ChangeSet[] sets = findChangeSets(info);
				if (sets.length == 0) {
					rootSet.add(info);
				} else {
					for (int j = 0; j < sets.length; j++) {
						ChangeSet set = sets[j];
						SyncInfoSet targetSet = getSyncInfoSet(set);
						if (targetSet == null) {
							// This will add all the appropriate sync info to the set
							createSyncInfoSet(set);
						} else {
							targetSet.add(info);
						}
					}
				}
			}
		}
		rootSet.endInput(null);
	}

	private ChangeSet[] findChangeSets(SyncInfo info) {
		ActiveChangeSetManager manager = getActiveChangeSetManager();
		ChangeSet[] sets = manager.getSets();
		List<ChangeSet> result = new ArrayList<>();
		for (int i = 0; i < sets.length; i++) {
			ChangeSet set = sets[i];
			if (set.contains(info.getLocal())) {
				result.add(set);
			}
		}
		return result.toArray(new ChangeSet[result.size()]);
	}

	/*
	 * Return if this sync info is an outgoing change.
	 */
	private boolean isLocalChange(SyncInfo info) {
		if (!info.getComparator().isThreeWay()) {
			try {
				// Obtain the sync info from the subscriber and use it to see if the change is local
				info = ((SubscriberChangeSetManager)getActiveChangeSetManager()).getSubscriber().getSyncInfo(info.getLocal());
			} catch (TeamException e) {
				TeamUIPlugin.log(e);
			}
		}
		return (info.getComparator().isThreeWay()
				&& ((info.getKind() & SyncInfo.DIRECTION_MASK) == SyncInfo.OUTGOING ||
						(info.getKind() & SyncInfo.DIRECTION_MASK) == SyncInfo.CONFLICTING));
	}

	public SyncInfoTree getRootSet() {
		return rootSet;
	}

	/*
	 * Add the set from the collector.
	 */
	public void add(ChangeSet set) {
		SyncInfoSet targetSet = getSyncInfoSet(set);
		if (targetSet == null) {
			createSyncInfoSet(set);
		}
		if (listener != null) {
			listener.setAdded(set);
		}
	}

	private SyncInfoTree createSyncInfoSet(ChangeSet set) {
		SyncInfoTree sis = getSyncInfoSet(set);
		// Register the listener last since the add will
		// look for new elements
		boolean added = false;
		// Use a variable to ensure that both begin and end are invoked
		try {
			if (sis == null) {
				sis = new SyncInfoTree();
				activeSets.put(set, sis);
				added = true;
			}
			sis.beginInput();
			if (!sis.isEmpty())
				sis.removeAll(sis.getResources());
			sis.addAll(getSyncInfos(set));
		} finally {
			if (sis != null)
				sis.endInput(null);
		}
		if (added) {
			((DiffChangeSet)set).getDiffTree().addDiffChangeListener(this);
			if (listener != null)
				listener.setAdded(set);
		}
		return sis;
	}

	private SyncInfoSet getSyncInfos(ChangeSet set) {
		IDiff[] diffs = ((ResourceDiffTree)((DiffChangeSet)set).getDiffTree()).getDiffs();
		return asSyncInfoSet(diffs);
	}

	private SyncInfoSet asSyncInfoSet(IDiff[] diffs) {
		SyncInfoSet result = new SyncInfoSet();
		for (int i = 0; i < diffs.length; i++) {
			IDiff diff = diffs[i];
			if (select(diff)) {
				SyncInfo info = asSyncInfo(diff);
				if (info != null)
					result.add(info);
			}
		}
		return result;
	}

	private SyncInfo asSyncInfo(IDiff diff) {
		try {
			return ((SubscriberParticipant)getConfiguration().getParticipant()).getSubscriber().getSyncInfo(ResourceDiffTree.getResourceFor(diff));
		} catch (TeamException e) {
			TeamUIPlugin.log(e);
		}
		return null;
	}

	private boolean select(IDiff diff) {
		return getSeedSet().getSyncInfo(ResourceDiffTree.getResourceFor(diff)) != null;
	}

	/* private */ SyncInfo getSyncInfo(IPath path) {
		return getSyncInfo(getSeedSet(), path);
	}

	/* private */ IResource[] getResources(SyncInfoSet set, IPath[] paths) {
		List<IResource> result = new ArrayList<>();
		for (int i = 0; i < paths.length; i++) {
			IPath path = paths[i];
			SyncInfo info = getSyncInfo(set, path);
			if (info != null) {
				result.add(info.getLocal());
			}
		}
		return result.toArray(new IResource[result.size()]);
	}

	private SyncInfo getSyncInfo(SyncInfoSet set, IPath path) {
		SyncInfo[] infos = set.getSyncInfos();
		for (int i = 0; i < infos.length; i++) {
			SyncInfo info = infos[i];
			if (info.getLocal().getFullPath().equals(path))
				return info;
		}
		return null;
	}

	/*
	 * Remove the set from the collector.
	 */
	public void remove(ChangeSet set) {
		((DiffChangeSet)set).getDiffTree().removeDiffChangeListener(this);
		activeSets.remove(set);
		if (listener != null) {
			listener.setRemoved(set);
		}
	}

	/*
	 * Return the sync info set for the given active change set
	 * or null if there isn't one.
	 */
	public SyncInfoTree getSyncInfoSet(ChangeSet set) {
		return (SyncInfoTree)activeSets.get(set);
	}

	private ChangeSet getChangeSet(IDiffTree tree) {
		for (Iterator iter = activeSets.keySet().iterator(); iter.hasNext();) {
			ChangeSet changeSet = (ChangeSet) iter.next();
			if (((DiffChangeSet)changeSet).getDiffTree() == tree) {
				return changeSet;
			}
		}
		return null;
	}

	private boolean select(SyncInfo info) {
		return getSeedSet().getSyncInfo(info.getLocal()) != null;
	}

	private SyncInfoSet getSeedSet() {
		return provider.getSyncInfoSet();
	}

	public void dispose() {
		getActiveChangeSetManager().removeListener(activeChangeSetListener);
	}

	/**
	 * Set the change set listener for this collector. There is
	 * only one for this type of collector.
	 * @param listener change set change listener
	 */
	public void setChangeSetChangeListener(IChangeSetChangeListener listener) {
		this.listener = listener;
		if (listener == null) {
			getActiveChangeSetManager().removeListener(activeChangeSetListener);
		} else {
			getActiveChangeSetManager().addListener(activeChangeSetListener);
		}
	}

	@Override
	public void diffsChanged(final IDiffChangeEvent event, IProgressMonitor monitor) {
		provider.performUpdate(monitor1 -> {
			ChangeSet changeSet = getChangeSet(event.getTree());
			if (changeSet != null) {
				SyncInfoSet targetSet = getSyncInfoSet(changeSet);
				if (targetSet != null) {
					targetSet.removeAll(getResources(targetSet, event.getRemovals()));
					targetSet.addAll(asSyncInfoSet(event.getAdditions()));
					targetSet.addAll(asSyncInfoSet(event.getChanges()));
					rootSet.removeAll(((IResourceDiffTree)event.getTree()).getAffectedResources());
				}
			}
		}, true /* preserver expansion */, true /* run in UI thread */);
	}

	@Override
	public void propertyChanged(IDiffTree tree, int property, IPath[] paths) {
		// Nothing to do
	}
}
