/*******************************************************************************
 * Copyright (c) 2000, 2017 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *     Martin Burger <m@rtin-burger.de> patch for #93810 and #93901
 *******************************************************************************/
package org.eclipse.compare.internal.patch;

import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.eclipse.compare.internal.core.Messages;
import org.eclipse.compare.internal.core.patch.DiffProject;
import org.eclipse.compare.internal.core.patch.FileDiffResult;
import org.eclipse.compare.internal.core.patch.FilePatch2;
import org.eclipse.compare.internal.core.patch.Hunk;
import org.eclipse.compare.internal.core.patch.PatchReader;
import org.eclipse.compare.patch.IHunk;
import org.eclipse.compare.patch.IHunkFilter;
import org.eclipse.compare.patch.PatchConfiguration;
import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.resources.IContainer;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IMarker;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ProjectScope;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.preferences.IScopeContext;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.jface.text.TextUtilities;

/**
 * A Patcher
 * - knows how to parse various patch file formats into some in-memory structure,
 * - holds onto the parsed data and the options to use when applying the patches,
 * - knows how to apply the patches to files and folders.
 */
public class Patcher implements IHunkFilter {

	static protected final String REJECT_FILE_EXTENSION= ".rej"; //$NON-NLS-1$

	static protected final String MARKER_TYPE= "org.eclipse.compare.rejectedPatchMarker"; //$NON-NLS-1$

	/**
	 * Property used to associate a patcher with a {@link PatchConfiguration}
	 */
	public static final String PROP_PATCHER = "org.eclipse.compare.patcher"; //$NON-NLS-1$

	public interface IFileValidator {
		boolean validateResources(IFile[] array);
	}

	// diff formats
	//	private static final int CONTEXT= 0;
	//	private static final int ED= 1;
	//	private static final int NORMAL= 2;
	//	private static final int UNIFIED= 3;

	private FilePatch2[] fDiffs;
	private IResource fTarget;
	// patch options
	private Set disabledElements = new HashSet();
	private Map<FilePatch2, FileDiffResult> diffResults = new HashMap<>();
	private final Map<FilePatch2, byte[]> contentCache = new HashMap<>();
	private Set<Hunk> mergedHunks = new HashSet<>();

	private final PatchConfiguration configuration;
	private boolean fGenerateRejectFile = false;

	public Patcher() {
		configuration = new PatchConfiguration();
		configuration.setProperty(PROP_PATCHER, this);
		configuration.addHunkFilter(this);
	}

	/*
	 * Returns an array of Diffs after a successful call to <code>parse</code>.
	 * If <code>parse</code> hasn't been called returns <code>null</code>.
	 */
	public FilePatch2[] getDiffs() {
		if (fDiffs == null)
			return new FilePatch2[0];
		return fDiffs;
	}

	public IPath getPath(FilePatch2 diff) {
		return diff.getStrippedPath(getStripPrefixSegments(), isReversed());
	}

	/*
	 * Returns <code>true</code> if new value differs from old.
	 */
	public boolean setStripPrefixSegments(int strip) {
		if (strip != getConfiguration().getPrefixSegmentStripCount()) {
			getConfiguration().setPrefixSegmentStripCount(strip);
			return true;
		}
		return false;
	}

	int getStripPrefixSegments() {
		return getConfiguration().getPrefixSegmentStripCount();
	}

	/*
	 * Returns <code>true</code> if new value differs from old.
	 */
	public boolean setFuzz(int fuzz) {
		if (fuzz != getConfiguration().getFuzz()) {
			getConfiguration().setFuzz(fuzz);
			return true;
		}
		return false;
	}

	public int getFuzz(){
		return getConfiguration().getFuzz();
	}

	/*
	 * Returns <code>true</code> if new value differs from old.
	 */
	public boolean setIgnoreWhitespace(boolean ignoreWhitespace) {
		if (ignoreWhitespace != getConfiguration().isIgnoreWhitespace()) {
			getConfiguration().setIgnoreWhitespace(ignoreWhitespace);
			return true;
		}
		return false;
	}

	public boolean isIgnoreWhitespace() {
		return getConfiguration().isIgnoreWhitespace();
	}

	public boolean isGenerateRejectFile() {
		return fGenerateRejectFile;
	}

	public void setGenerateRejectFile(boolean generateRejectFile) {
		fGenerateRejectFile = generateRejectFile;
	}

	//---- parsing patch files

	public void parse(IStorage storage) throws IOException, CoreException {
		BufferedReader reader = Utilities.createReader(storage);
		try {
			parse(reader);
		} finally {
			try {
				reader.close();
			} catch (IOException e) { //ignored
			}
		}
	}

	public void parse(BufferedReader reader) throws IOException {
		PatchReader patchReader = new PatchReader() {
			@Override
			protected FilePatch2 createFileDiff(IPath oldPath, long oldDate,
					IPath newPath, long newDate) {
				return new FilePatch(oldPath, oldDate, newPath, newDate);
			}
		};
		patchReader.parse(reader);
		patchParsed(patchReader);
	}

	protected void patchParsed(PatchReader patchReader) {
		fDiffs = patchReader.getDiffs();
	}

	public void countLines() {
		FilePatch2[] fileDiffs = getDiffs();
		for (int i = 0; i < fileDiffs.length; i++) {
			int addedLines = 0;
			int removedLines = 0;
			FilePatch2 fileDiff = fileDiffs[i];
			for (int j = 0; j < fileDiff.getHunkCount(); j++) {
				IHunk hunk = fileDiff.getHunks()[j];
				String[] lines = ((Hunk) hunk).getLines();
				for (int k = 0; k < lines.length; k++) {
					char c = lines[k].charAt(0);
					switch (c) {
					case '+':
						addedLines++;
						continue;
					case '-':
						removedLines++;
						continue;
					}
				}
			}
			fileDiff.setAddedLines(addedLines);
			fileDiff.setRemovedLines(removedLines);
		}
	}

	//---- applying a patch file

	public void applyAll(IProgressMonitor pm, IFileValidator validator) throws CoreException {

		int i;

		IFile singleFile= null;	// file to be patched
		IContainer container= null;
		if (fTarget instanceof IContainer)
			container= (IContainer) fTarget;
		else if (fTarget instanceof IFile) {
			singleFile= (IFile) fTarget;
			container= singleFile.getParent();
		} else {
			Assert.isTrue(false);
		}

		// get all files to be modified in order to call validateEdit
		List<IFile> list= new ArrayList<>();
		if (singleFile != null)
			list.add(singleFile);
		else {
			for (i= 0; i < fDiffs.length; i++) {
				FilePatch2 diff= fDiffs[i];
				if (isEnabled(diff)) {
					switch (diff.getDiffType(isReversed())) {
					case FilePatch2.CHANGE:
						list.add(createPath(container, getPath(diff)));
						break;
					}
				}
			}
		}
		if (! validator.validateResources(list.toArray(new IFile[list.size()]))) {
			return;
		}

		final int WORK_UNIT= 10;
		if (pm != null) {
			String message= Messages.Patcher_0;
			pm.beginTask(message, fDiffs.length*WORK_UNIT);
		}

		for (i= 0; i < fDiffs.length; i++) {

			int workTicks= WORK_UNIT;

			FilePatch2 diff= fDiffs[i];
			if (isEnabled(diff)) {

				IPath path= getPath(diff);
				if (pm != null)
					pm.subTask(path.toString());

				IFile file= singleFile != null
								? singleFile
								: createPath(container, path);

				List<Hunk> failed= new ArrayList<>();

				int type= diff.getDiffType(isReversed());
				switch (type) {
				case FilePatch2.ADDITION:
					// patch it and collect rejected hunks
					List<String> result= apply(diff, file, true, failed);
					if (result != null)
						store(LineReader.createString(isPreserveLineDelimeters(), result), file, new SubProgressMonitor(pm, workTicks));
					workTicks-= WORK_UNIT;
					break;
				case FilePatch2.DELETION:
					file.delete(true, true, new SubProgressMonitor(pm, workTicks));
					workTicks-= WORK_UNIT;
					break;
				case FilePatch2.CHANGE:
					// patch it and collect rejected hunks
					result= apply(diff, file, false, failed);
					if (result != null)
						store(LineReader.createString(isPreserveLineDelimeters(), result), file, new SubProgressMonitor(pm, workTicks));
					workTicks-= WORK_UNIT;
					break;
				}

				if (isGenerateRejectFile() && failed.size() > 0) {
					IPath pp = getRejectFilePath(path);
					file= createPath(container, pp);
					if (file != null) {
						store(getRejected(failed), file, pm);
						try {
							IMarker marker= file.createMarker(MARKER_TYPE);
							marker.setAttribute(IMarker.MESSAGE, Messages.Patcher_1);
							marker.setAttribute(IMarker.PRIORITY, IMarker.PRIORITY_HIGH);
						} catch (CoreException ex) {
							// NeedWork
						}
					}
				}
			}

			if (pm != null) {
				if (pm.isCanceled())
					break;
				if (workTicks > 0)
					pm.worked(workTicks);
			}
		}
	}

	private IPath getRejectFilePath(IPath path) {
		IPath pp= null;
		if (path.segmentCount() > 1) {
			pp= path.removeLastSegments(1);
			pp= pp.append(path.lastSegment() + REJECT_FILE_EXTENSION);
		} else
			pp= new Path(path.lastSegment() + REJECT_FILE_EXTENSION);
		return pp;
	}

	List<String> apply(FilePatch2 diff, IFile file, boolean create, List<Hunk> failedHunks) {
		FileDiffResult result = getDiffResult(diff);
		List<String> lines = LineReader.load(file, create);
		result.patch(lines, null);
		failedHunks.addAll(result.getFailedHunks());
		if (hasCachedContents(diff)) {
			// Used the cached contents since they would have been provided by the user
			return getCachedLines(diff);
		} else if (!result.hasMatches()) {
			// Return null if there were no matches
			return null;
		}
		return result.getLines();
	}

	/*
	 * Converts the string into bytes and stores them in the given file.
	 */
	protected void store(String contents, IFile file, IProgressMonitor pm) throws CoreException {

		if (!file.exists()) {
			if (FileBuffers.getTextFileBufferManager().isTextFileLocation(file.getFullPath(), true)) {
				// For new text files use the line delimiter as defined in the workspace
				String expectedLD= getLineDelimiterPreference(file);
				if (expectedLD != null) {
					String patchLD= TextUtilities.determineLineDelimiter(contents, expectedLD);
					if (!expectedLD.equals(patchLD))
						contents= contents.replaceAll(patchLD, expectedLD);
				}
			}
		}

		byte[] bytes;
		try {
			bytes= contents.getBytes(Utilities.getCharset(file));
		} catch (UnsupportedEncodingException x) {
			// uses default encoding
			bytes= contents.getBytes();
		}

		store(bytes,file, pm);
	}

	private static String getLineDelimiterPreference(IFile file) {
		IScopeContext[] scopeContext;
		if (file != null && file.getProject() != null) {
			// project preference
			scopeContext= new IScopeContext[] { new ProjectScope(file.getProject()) };
			String lineDelimiter= Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext);
			if (lineDelimiter != null)
				return lineDelimiter;
		}
		// workspace preference
		scopeContext= new IScopeContext[] { InstanceScope.INSTANCE };
		return Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext);
	}

	protected void store(byte[] bytes, IFile file, IProgressMonitor pm) throws CoreException {
		InputStream is= new ByteArrayInputStream(bytes);
		try {
			if (file.exists()) {
				file.setContents(is, false, true, pm);
			} else {
				file.create(is, false, pm);
			}
		} finally {
			if (is != null)
				try {
					is.close();
				} catch(IOException ex) {
					// silently ignored
				}
		}
	}

	public boolean isPreserveLineDelimeters() {
		return true;
	}

	public static String getRejected(List<Hunk> failedHunks) {
		if (failedHunks.size() <= 0)
			return null;

		String lineSeparator= System.getProperty("line.separator"); //$NON-NLS-1$
		StringBuilder sb= new StringBuilder();
		Iterator<Hunk> iter= failedHunks.iterator();
		while (iter.hasNext()) {
			Hunk hunk= iter.next();
			sb.append(hunk.getRejectedDescription());
			sb.append(lineSeparator);
			sb.append(hunk.getContent());
		}
		return sb.toString();
	}

	/*
	 * Ensures that a file with the given path exists in
	 * the given container. Folder are created as necessary.
	 */
	protected IFile createPath(IContainer container, IPath path) throws CoreException {
		if (path.segmentCount() > 1) {
			IContainer childContainer;
			if (container instanceof IWorkspaceRoot) {
				IProject project = ((IWorkspaceRoot)container).getProject(path.segment(0));
				if (!project.exists())
					project.create(null);
				if (!project.isOpen())
					project.open(null);
				childContainer = project;
			} else {
				IFolder f= container.getFolder(path.uptoSegment(1));
				if (!f.exists())
					f.create(false, true, null);
				childContainer = f;
			}
			return createPath(childContainer, path.removeFirstSegments(1));
		}
		// a leaf
		return container.getFile(path);
	}

	public IResource getTarget() {
		return fTarget;
	}

	public void setTarget(IResource target) {
		fTarget= target;
	}


	public IFile getTargetFile(FilePatch2 diff) {
		IPath path = diff.getStrippedPath(getStripPrefixSegments(), isReversed());
		return existsInTarget(path);
	}

	/**
	 * Iterates through all of the resources contained in the Patch Wizard target
	 * and looks to for a match to the passed in file
	 * @param path
	 * @return IFile which matches the passed in path or null if none found
	 */
	public IFile existsInTarget(IPath path) {
		if (fTarget instanceof IFile) { // special case
			IFile file= (IFile) fTarget;
			if (matches(file.getFullPath(), path))
				return file;
		} else if (fTarget instanceof IContainer) {
			IContainer c= (IContainer) fTarget;
			if (c.exists(path))
				return c.getFile(path);
		}
		return null;
	}

	/**
	 * Returns true if path completely matches the end of fullpath
	 * @param fullpath
	 * @param path
	 * @return true if path matches, false otherwise
	 */
	private boolean matches(IPath fullpath, IPath path) {
		for (IPath p= fullpath; path.segmentCount()<=p.segmentCount(); p= p.removeFirstSegments(1)) {
			if (p.equals(path))
				return true;
		}
		return false;
	}

	public int calculatePrefixSegmentCount() {
		//Update prefix count - go through all of the diffs and find the smallest
		//path segment contained in all diffs.
		int length= 99;
		if (fDiffs!=null) {
			for (int i= 0; i<fDiffs.length; i++) {
				FilePatch2 diff= fDiffs[i];
				length= Math.min(length, diff.segmentCount());
			}
			if (ResourcesPlugin.getWorkspace().getRoot().equals(fTarget))
				length--;
		}
		return length;
	}

	public void addDiff(FilePatch2 newDiff){
		FilePatch2[] temp = new FilePatch2[fDiffs.length + 1];
		System.arraycopy(fDiffs,0, temp, 0, fDiffs.length);
		temp[fDiffs.length] = newDiff;
		fDiffs = temp;
	}

	public void removeDiff(FilePatch2 diffToRemove){
		FilePatch2[] temp = new FilePatch2[fDiffs.length - 1];
		int counter = 0;
		for (int i = 0; i < fDiffs.length; i++) {
			if (fDiffs[i] != diffToRemove){
				temp[counter++] = fDiffs[i];
			}
		}
		fDiffs = temp;
	}

	public void setEnabled(Object element, boolean enabled) {
		if (element instanceof DiffProject)
			setEnabledProject((DiffProject) element, enabled);
		if (element instanceof FilePatch2)
			setEnabledFile((FilePatch2)element, enabled);
		if (element instanceof Hunk)
			setEnabledHunk((Hunk) element, enabled);
	}

	private void setEnabledProject(DiffProject projectDiff, boolean enabled) {
		FilePatch2[] diffFiles = projectDiff.getFileDiffs();
		for (int i = 0; i < diffFiles.length; i++) {
			setEnabledFile(diffFiles[i], enabled);
		}
	}

	private void setEnabledFile(FilePatch2 fileDiff, boolean enabled) {
		IHunk[] hunks = fileDiff.getHunks();
		for (int i = 0; i < hunks.length; i++) {
			setEnabledHunk((Hunk) hunks[i], enabled);
		}
	}

	private void setEnabledHunk(Hunk hunk, boolean enabled) {
		if (enabled) {
			disabledElements.remove(hunk);
			FilePatch2 file = hunk.getParent();
			disabledElements.remove(file);
			DiffProject project = file.getProject();
			if (project != null)
				disabledElements.remove(project);
		} else {
			disabledElements.add(hunk);
			FilePatch2 file = hunk.getParent();
			if (disabledElements.containsAll(Arrays.asList(file.getHunks()))) {
				disabledElements.add(file);
				DiffProject project = file.getProject();
				if (project != null
						&& disabledElements.containsAll(Arrays.asList(project
								.getFileDiffs())))
					disabledElements.add(project);
			}
		}
	}

	public boolean isEnabled(Object element) {
		if (disabledElements.contains(element))
			return false;
		Object parent = getElementParent(element);
		if (parent == null)
			return true;
		return isEnabled(parent);
	}

	protected Object getElementParent(Object element) {
		if (element instanceof Hunk) {
			Hunk hunk = (Hunk) element;
			return hunk.getParent();
		}
		return null;
	}

	/**
	 * Calculate the fuzz factor that will allow the most hunks to be matched.
	 * @param monitor a progress monitor
	 * @return the fuzz factor or <code>-1</code> if no hunks could be matched
	 */
	public int guessFuzzFactor(IProgressMonitor monitor) {
		try {
			monitor.beginTask(Messages.Patcher_2, IProgressMonitor.UNKNOWN);
			FilePatch2[] diffs= getDiffs();
			if (diffs==null||diffs.length<=0)
				return -1;
			int fuzz= -1;
			for (int i= 0; i<diffs.length; i++) {
				FilePatch2 d= diffs[i];
				IFile file= getTargetFile(d);
				if (file != null && file.exists()) {
					List<String> lines= LineReader.load(file, false);
					FileDiffResult result = getDiffResult(d);
					int f = result.calculateFuzz(lines, monitor);
					if (f > fuzz)
						fuzz = f;
				}
			}
			return fuzz;
		} finally {
			monitor.done();
		}
	}

	public void refresh() {
		diffResults.clear();
		refresh(getDiffs());
	}

	public void refresh(FilePatch2[] diffs) {
		for (int i = 0; i < diffs.length; i++) {
			FilePatch2 diff = diffs[i];
			FileDiffResult result = getDiffResult(diff);
			((WorkspaceFileDiffResult)result).refresh();
		}
	}

	public FileDiffResult getDiffResult(FilePatch2 diff) {
		FileDiffResult result = diffResults.get(diff);
		if (result == null) {
			result = new WorkspaceFileDiffResult(diff, getConfiguration());
			diffResults.put(diff, result);
		}
		return result;
	}

	public PatchConfiguration getConfiguration() {
		return configuration;
	}

	/**
	 * Return the project that contains this diff or <code>null</code>
	 * if the patch is not a workspace patch.
	 * @param diff the diff
	 * @return the project that contains the diff
	 */
	public DiffProject getProject(FilePatch2 diff) {
		return diff.getProject();
	}

	/*
	 * Returns <code>true</code> if new value differs from old.
	 */
	public boolean setReversed(boolean reverse) {
		if (getConfiguration().isReversed() != reverse) {
			getConfiguration().setReversed(reverse);
			refresh();
			return true;
		}
		return false;
	}

	public boolean isReversed() {
		return getConfiguration().isReversed();
	}

	/**
	 * Cache the contents for the given file diff. These contents
	 * will be used for the diff when the patch is applied. When the
	 * patch is applied, it is assumed that the provided contents
	 * already have all relevant hunks applied.
	 * @param diff the file diff
	 * @param contents the contents for the file diff
	 */
	public void cacheContents(FilePatch2 diff, byte[] contents) {
		contentCache.put(diff, contents);
	}

	/**
	 * Return whether contents have been cached for the
	 * given file diff.
	 * @param diff the file diff
	 * @return whether contents have been cached for the file diff
	 * @see #cacheContents(FilePatch2, byte[])
	 */
	public boolean hasCachedContents(FilePatch2 diff) {
		return contentCache.containsKey(diff);
	}

	/**
	 * Return the content lines that are cached for the given
	 * file diff.
	 * @param diff the file diff
	 * @return the content lines that are cached for the file diff
	 */
	public List<String> getCachedLines(FilePatch2 diff) {
		byte[] contents = contentCache.get(diff);
		if (contents != null) {
			BufferedReader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(contents)));
			return LineReader.readLines(reader);
		}
		return null;
	}

	/**
	 * Return the contents that are cached for the given diff or
	 * <code>null</code> if there is no contents cached.
	 * @param diff the diff
	 * @return the contents that are cached for the given diff or
	 * <code>null</code>
	 */
	public byte[] getCachedContents(FilePatch2 diff) {
		return contentCache.get(diff);
	}

	/**
	 * Return whether the patcher has any cached contents.
	 * @return whether the patcher has any cached contents
	 */
	public boolean hasCachedContents() {
		return !contentCache.isEmpty();
	}

	/**
	 * Clear any cached contents.
	 */
	public void clearCachedContents() {
		contentCache.clear();
		mergedHunks.clear();
	}

	public void setProperty(String key, Object value) {
		getConfiguration().setProperty(key, value);
	}

	public Object getProperty(String key) {
		return getConfiguration().getProperty(key);
	}

	public boolean isManuallyMerged(Hunk hunk) {
		return mergedHunks.contains(hunk);
	}

	public void setManuallyMerged(Hunk hunk, boolean merged) {
		if (merged)
			mergedHunks.add(hunk);
		else
			mergedHunks.remove(hunk);
	}

	public IProject getTargetProject(FilePatch2 diff) {
		DiffProject dp = getProject(diff);
		if (dp != null)
			return Utilities.getProject(dp);
		IResource tr = getTarget();
		if (tr instanceof IWorkspaceRoot) {
			IWorkspaceRoot root = (IWorkspaceRoot) tr;
			return root.getProject(diff.getPath(isReversed()).segment(0));
		}
		return tr.getProject();
	}

	public static Patcher getPatcher(PatchConfiguration configuration) {
		return (Patcher)configuration.getProperty(PROP_PATCHER);
	}

	public boolean hasRejects() {
		for (Iterator<FileDiffResult> iterator = diffResults.values().iterator(); iterator.hasNext();) {
			FileDiffResult result = iterator.next();
			if (result.hasRejects())
				return true;
		}
		return false;
	}

	@Override
	public boolean select(IHunk hunk) {
		return isEnabled(hunk);
	}
}
