/*******************************************************************************
 * 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.core.mapping.provider;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IResourceRuleFactory;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.runtime.jobs.MultiRule;
import org.eclipse.osgi.util.NLS;
import org.eclipse.team.core.diff.IDiff;
import org.eclipse.team.core.diff.IThreeWayDiff;
import org.eclipse.team.core.history.IFileRevision;
import org.eclipse.team.core.mapping.DelegatingStorageMerger;
import org.eclipse.team.core.mapping.IMergeContext;
import org.eclipse.team.core.mapping.IMergeStatus;
import org.eclipse.team.core.mapping.IResourceDiff;
import org.eclipse.team.core.mapping.IResourceDiffTree;
import org.eclipse.team.core.mapping.IResourceMappingMerger;
import org.eclipse.team.core.mapping.IStorageMerger;
import org.eclipse.team.core.mapping.ISynchronizationScopeManager;
import org.eclipse.team.internal.core.Messages;
import org.eclipse.team.internal.core.Policy;
import org.eclipse.team.internal.core.TeamPlugin;
import org.eclipse.team.internal.core.mapping.SyncInfoToDiffConverter;

/**
 * Provides the context for an <code>IResourceMappingMerger</code>.
 * It provides access to the ancestor and remote resource mapping contexts
 * so that resource mapping mergers can attempt head-less auto-merges.
 * The ancestor context is only required for merges while the remote
 * is required for both merge and replace.
 *
 * @see IResourceMappingMerger
 * @since 3.2
 */
public abstract class MergeContext extends SynchronizationContext implements IMergeContext {

	/**
	 * Create a merge context.
	 *
	 * @param manager   the manager that defines the scope of the synchronization
	 * @param type      the type of synchronization (ONE_WAY or TWO_WAY)
	 * @param deltaTree the sync info tree that contains all out-of-sync resources
	 */
	protected MergeContext(ISynchronizationScopeManager manager, int type, IResourceDiffTree deltaTree) {
		super(manager, type, deltaTree);
	}

	@Override
	public void reject(final IDiff[] diffs, IProgressMonitor monitor) throws CoreException {
		run(monitor1 -> {
			for (int i = 0; i < diffs.length; i++) {
				IDiff node = diffs[i];
				reject(node, monitor1);
			}
		}, getMergeRule(diffs), IResource.NONE, monitor);
	}

	@Override
	public void markAsMerged(final IDiff[] nodes, final boolean inSyncHint, IProgressMonitor monitor) throws CoreException {
		run(monitor1 -> {
			for (int i = 0; i < nodes.length; i++) {
				IDiff node = nodes[i];
				markAsMerged(node, inSyncHint, monitor1);
			}
		}, getMergeRule(nodes), IResource.NONE, monitor);
	}

	@Override
	public IStatus merge(final IDiff[] deltas, final boolean force, IProgressMonitor monitor) throws CoreException {
		final List<IFile> failedFiles = new ArrayList<>();
		run(monitor1 -> {
			try {
				monitor1.beginTask(null, deltas.length * 100);
				for (int i = 0; i < deltas.length; i++) {
					IDiff delta = deltas[i];
					IStatus s = merge(delta, force, Policy.subMonitorFor(monitor1, 100));
					if (!s.isOK()) {
						if (s.getCode() == IMergeStatus.CONFLICTS) {
							failedFiles.addAll(Arrays.asList(((IMergeStatus)s).getConflictingFiles()));
						} else {
							throw new CoreException(s);
						}
					}
				}
			} finally {
				monitor1.done();
			}
		}, getMergeRule(deltas), IWorkspace.AVOID_UPDATE, monitor);
		if (failedFiles.isEmpty()) {
			return Status.OK_STATUS;
		} else {
			return new MergeStatus(TeamPlugin.ID, Messages.MergeContext_0, failedFiles.toArray(new IFile[failedFiles.size()]));
		}
	}

	@Override
	public IStatus merge(IDiff diff, boolean ignoreLocalChanges, IProgressMonitor monitor) throws CoreException {
		Policy.checkCanceled(monitor);
		IResource resource = getDiffTree().getResource(diff);
		if (resource.getType() != IResource.FILE) {
			if (diff instanceof IThreeWayDiff) {
				IThreeWayDiff twd = (IThreeWayDiff) diff;
				if ((ignoreLocalChanges || getMergeType() == TWO_WAY)
						&& resource.getType() == IResource.FOLDER
						&& twd.getKind() == IDiff.ADD
						&& twd.getDirection() == IThreeWayDiff.OUTGOING
						&& ((IFolder)resource).members().length == 0) {
					// Delete the local folder addition
					((IFolder)resource).delete(false, monitor);
				} else if (resource.getType() == IResource.FOLDER
						&& !resource.exists()
						&& twd.getKind() == IDiff.ADD
						&& twd.getDirection() == IThreeWayDiff.INCOMING) {
					ensureParentsExist(resource, monitor);
					((IFolder)resource).create(false, true, monitor);
					makeInSync(diff, monitor);
				}
			}
			return Status.OK_STATUS;
		}
		if (diff instanceof IThreeWayDiff && !ignoreLocalChanges && getMergeType() == THREE_WAY) {
			IThreeWayDiff twDelta = (IThreeWayDiff) diff;
			int direction = twDelta.getDirection();
			if (direction == IThreeWayDiff.OUTGOING) {
				// There's nothing to do so return OK
				return Status.OK_STATUS;
			}
			if (direction == IThreeWayDiff.INCOMING) {
				// Just copy the stream since there are no conflicts
				performReplace(diff, monitor);
				return Status.OK_STATUS;
			}
			// direction == SyncInfo.CONFLICTING
			int type = twDelta.getKind();
			if (type == IDiff.REMOVE) {
				makeInSync(diff, monitor);
				return Status.OK_STATUS;
			}
			// type == SyncInfo.CHANGE
			IResourceDiff remoteChange = (IResourceDiff)twDelta.getRemoteChange();
			IFileRevision remote = null;
			if (remoteChange != null) {
				remote = remoteChange.getAfterState();
			}
			if (remote == null || !getLocalFile(diff).exists()) {
				// Nothing we can do so return a conflict status
				// TODO: Should we handle the case where the local and remote have the same contents for a conflicting addition?
				return new MergeStatus(TeamPlugin.ID, NLS.bind(Messages.MergeContext_1, new String[] { diff.getPath().toString() }), new IFile[] { getLocalFile(diff) });
			}
			// We have a conflict, a local, base and remote so we can do
			// a three-way merge
			return performThreeWayMerge(twDelta, monitor);
		} else {
			performReplace(diff, monitor);
			return Status.OK_STATUS;
		}

	}

	/**
	 * Perform a three-way merge on the given three-way diff that contains a content conflict.
	 * By default, this method makes use of {@link IStorageMerger} instances registered
	 * with the <code>storageMergers</code> extension point. Note that the ancestor
	 * of the given diff may be missing. Some {@link IStorageMerger} instances
	 * can still merge without an ancestor so we need to consult the
	 * appropriate merger to find out.
	 * @param diff the diff
	 * @param monitor a progress monitor
	 * @return a status indicating the results of the merge
	 */
	protected IStatus performThreeWayMerge(final IThreeWayDiff diff, IProgressMonitor monitor) throws CoreException {
		final IStatus[] result = new IStatus[] { Status.OK_STATUS };
		run(monitor1 -> {
			monitor1.beginTask(null, 100);
			IResourceDiff localDiff = (IResourceDiff)diff.getLocalChange();
			IResourceDiff remoteDiff = (IResourceDiff)diff.getRemoteChange();
			IStorageMerger merger = getAdapter(IStorageMerger.class);
			if (merger == null)
				merger = DelegatingStorageMerger.getInstance();
			IFile file = (IFile)localDiff.getResource();
			monitor1.subTask(NLS.bind(Messages.MergeContext_5, file.getFullPath().toString()));
			String osEncoding = file.getCharset();
			IFileRevision ancestorState = localDiff.getBeforeState();
			IFileRevision remoteState = remoteDiff.getAfterState();
			IStorage ancestorStorage;
			if (ancestorState != null)
				ancestorStorage = ancestorState.getStorage(Policy.subMonitorFor(monitor1, 30));
			else
				ancestorStorage = null;
			IStorage remoteStorage = remoteState.getStorage(Policy.subMonitorFor(monitor1, 30));
			OutputStream os = getTempOutputStream(file);
			try {
				IStatus status = merger.merge(os, osEncoding, ancestorStorage, file, remoteStorage, Policy.subMonitorFor(monitor1, 30));
				if (status.isOK()) {
					file.setContents(getTempInputStream(file, os), false, true, Policy.subMonitorFor(monitor1, 5));
					markAsMerged(diff, false, Policy.subMonitorFor(monitor1, 5));
				} else {
					status = new MergeStatus(status.getPlugin(), status.getMessage(), new IFile[]{file});
				}
				result[0] = status;
			} finally {
				disposeTempOutputStream(file, os);
			}
			monitor1.done();
		}, getMergeRule(diff), IWorkspace.AVOID_UPDATE, monitor);
		return result[0];
	}

	private void disposeTempOutputStream(IFile file, OutputStream output) {
		if (output instanceof ByteArrayOutputStream)
			return;
		// We created a temporary file so we need to clean it up
		try {
			// First make sure the output stream is closed
			// so that file deletion will not fail because of that.
			if (output != null)
				output.close();
		} catch (IOException e) {
			// Ignore
		}
		File tmpFile = getTempFile(file);
		if (tmpFile.exists())
			tmpFile.delete();
	}

	private OutputStream getTempOutputStream(IFile file) throws CoreException {
		File tmpFile = getTempFile(file);
		if (tmpFile.exists())
			tmpFile.delete();
		File parent = tmpFile.getParentFile();
		if (!parent.exists())
			parent.mkdirs();
		try {
			return new BufferedOutputStream(new FileOutputStream(tmpFile));
		} catch (FileNotFoundException e) {
			TeamPlugin.log(IStatus.ERROR, NLS.bind("Could not open temporary file {0} for writing: {1}", new String[] { tmpFile.getAbsolutePath(), e.getMessage() }), e); //$NON-NLS-1$
			return new ByteArrayOutputStream();
		}
	}

	private InputStream getTempInputStream(IFile file, OutputStream output) throws CoreException {
		if (output instanceof ByteArrayOutputStream) {
			ByteArrayOutputStream baos = (ByteArrayOutputStream) output;
			return new ByteArrayInputStream(baos.toByteArray());
		}
		// We created a temporary file so we need to open an input stream on it
		try {
			// First make sure the output stream is closed
			if (output != null)
				output.close();
		} catch (IOException e) {
			// Ignore
		}
		File tmpFile = getTempFile(file);
		try {
			return new BufferedInputStream(new FileInputStream(tmpFile));
		} catch (FileNotFoundException e) {
			throw new CoreException(new Status(IStatus.ERROR, TeamPlugin.ID, IMergeStatus.INTERNAL_ERROR, NLS.bind(Messages.MergeContext_4, new String[] { tmpFile.getAbsolutePath(), e.getMessage() }), e));
		}
	}

	private File getTempFile(IFile file) {
		return TeamPlugin.getPlugin().getStateLocation().append(".tmp").append(file.getName() + ".tmp").toFile(); //$NON-NLS-1$ //$NON-NLS-2$
	}

	private IFile getLocalFile(IDiff delta) {
		return ResourcesPlugin.getWorkspace().getRoot().getFile(delta.getPath());
	}

	/**
	 * Make the local state of the resource associated with the given diff match
	 * that of the remote. This method is invoked by the
	 * {@link #merge(IDiff, boolean, IProgressMonitor)} method. By default, it
	 * either overwrites the local contexts with the remote contents if both
	 * exist, deletes the local if the remote does not exists or adds the local
	 * if the local doesn't exist but the remote does. It then calls
	 * {@link #makeInSync(IDiff, IProgressMonitor)} to give subclasses a change
	 * to make the file associated with the diff in-sync.
	 *
	 * @param diff
	 *            the diff whose local is to be replaced
	 * @param monitor
	 *            a progress monitor
	 * @throws CoreException
	 */
	protected void performReplace(final IDiff diff, IProgressMonitor monitor) throws CoreException {
		IResourceDiff d;
		IFile file = getLocalFile(diff);
		IFileRevision remote = null;
		if (diff instanceof IResourceDiff) {
			d = (IResourceDiff) diff;
			remote = d.getAfterState();
		} else {
			d = (IResourceDiff)((IThreeWayDiff)diff).getRemoteChange();
			if (d != null)
				remote = d.getAfterState();
		}
		if (d == null) {
			d = (IResourceDiff)((IThreeWayDiff)diff).getLocalChange();
			if (d != null)
				remote = d.getBeforeState();
		}

		// Only perform the replace if a local or remote change was found
		if (d != null) {
			performReplace(diff, file, remote, monitor);
		}
	}

	/**
	 * Method that is invoked from
	 * {@link #performReplace(IDiff, IProgressMonitor)} after the local has been
	 * changed to match the remote. Subclasses may override
	 * {@link #performReplace(IDiff, IProgressMonitor)} or this method in order
	 * to properly reconcile the synchronization state. This method is also
	 * invoked from {@link #merge(IDiff, boolean, IProgressMonitor)} if deletion
	 * conflicts are encountered. It can also be invoked from that same method if
	 * a folder is created due to an incoming folder addition.
	 *
	 * @param diff
	 *            the diff whose local is now in-sync
	 * @param monitor
	 *            a progress monitor
	 * @throws CoreException
	 */
	protected abstract void makeInSync(IDiff diff, IProgressMonitor monitor) throws CoreException;

	private void performReplace(final IDiff diff, final IFile file, final IFileRevision remote, IProgressMonitor monitor) throws CoreException {
		run(monitor1 -> {
			try {
				monitor1.beginTask(null, 100);
				monitor1.subTask(NLS.bind(Messages.MergeContext_6, file.getFullPath().toString()));
				if ((remote == null || !remote.exists()) && file.exists()) {
					file.delete(false, true, Policy.subMonitorFor(monitor1, 95));
				} else if (remote != null) {
					ensureParentsExist(file, monitor1);
					InputStream stream = remote.getStorage(monitor1).getContents();
					stream = new BufferedInputStream(stream);
					try {
						if (file.exists()) {
							file.setContents(stream, false, true, Policy.subMonitorFor(monitor1, 95));
						} else {
							file.create(stream, false, Policy.subMonitorFor(monitor1, 95));
						}
					} finally {
						try {
							stream.close();
						} catch (IOException e) {
							// Ignore
						}
					}
				}
				// Performing a replace should leave the file in-sync
				makeInSync(diff, Policy.subMonitorFor(monitor1, 5));
			} finally {
				monitor1.done();
			}
		}, getMergeRule(diff), IWorkspace.AVOID_UPDATE, monitor);
	}

	/**
	 * Ensure that the parent folders of the given resource exist.
	 * This method is invoked from {@link #performReplace(IDiff, IProgressMonitor)}
	 * for files that are being merged that do not exist locally.
	 * By default, this method creates the parents using
	 * {@link IFolder#create(boolean, boolean, IProgressMonitor)}.
	 * Subclasses may override.
	 * @param resource a resource
	 * @param monitor a progress monitor
	 * @throws CoreException if an error occurs
	 */
	protected void ensureParentsExist(IResource resource, IProgressMonitor monitor) throws CoreException {
		IContainer parent = resource.getParent();
		if (parent.getType() != IResource.FOLDER) {
			// this method will only create folders
			return;
		}
		if (!parent.exists()) {
			ensureParentsExist(parent, monitor);
			((IFolder)parent).create(false, true, monitor);
		}
	}

	/**
	 * Default implementation of <code>run</code> that invokes the
	 * corresponding <code>run</code> on {@link org.eclipse.core.resources.IWorkspace}.
	 * @see org.eclipse.team.core.mapping.IMergeContext#run(org.eclipse.core.resources.IWorkspaceRunnable, org.eclipse.core.runtime.jobs.ISchedulingRule, int, org.eclipse.core.runtime.IProgressMonitor)
	 */
	@Override
	public void run(IWorkspaceRunnable runnable, ISchedulingRule rule, int flags, IProgressMonitor monitor) throws CoreException {
		ResourcesPlugin.getWorkspace().run(runnable, rule, flags, monitor);
	}

	/**
	 * Default implementation that returns the resource itself if it exists
	 * and the first existing parent if the resource does not exist.
	 * Subclass should override to provide the appropriate rule.
	 * @see org.eclipse.team.core.mapping.IMergeContext#getMergeRule(IDiff)
	 */
	@Override
	public ISchedulingRule getMergeRule(IDiff diff) {
		IResource resource = getDiffTree().getResource(diff);
		IResourceRuleFactory ruleFactory = ResourcesPlugin.getWorkspace().getRuleFactory();
		ISchedulingRule rule;
		if (!resource.exists()) {
			// for additions return rule for all parents that need to be created
			IContainer parent = resource.getParent();
			while (!parent.exists()) {
				resource = parent;
				parent = parent.getParent();
			}
			rule = ruleFactory.createRule(resource);
		} else if (SyncInfoToDiffConverter.getRemote(diff) == null){
			rule = ruleFactory.deleteRule(resource);
		} else {
			rule = ruleFactory.modifyRule(resource);
		}
		return rule;
	}

	@Override
	public ISchedulingRule getMergeRule(IDiff[] deltas) {
		ISchedulingRule result = null;
		for (int i = 0; i < deltas.length; i++) {
			IDiff node = deltas[i];
			ISchedulingRule rule = getMergeRule(node);
			if (result == null) {
				result = rule;
			} else {
				result = MultiRule.combine(result, rule);
			}
		}
		return result;
	}

	@Override
	public int getMergeType() {
		return getType();
	}

	@Override
	@SuppressWarnings("unchecked")
	public <T> T getAdapter(Class<T> adapter) {
		if (adapter == IStorageMerger.class) {
			return (T) DelegatingStorageMerger.getInstance();
		}
		return super.getAdapter(adapter);
	}
}
