/*******************************************************************************
 * Copyright (c) 2000, 2011 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.compare.internal.core.patch;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.compare.patch.*;
import org.eclipse.core.runtime.Assert;

/**
 * A Hunk describes a range of changed lines and some context lines.
 */
public class Hunk implements IHunk {
	private FilePatch2 fParent;
	private int fOldStart, fOldLength;
	private int fNewStart, fNewLength;
	private String[] fLines;
	private int hunkType;
	private String charset = null;

	public static Hunk createHunk(FilePatch2 parent, int[] oldRange, int[] newRange,
			List<String> lines, boolean hasLineAdditions, boolean hasLineDeletions, boolean hasContextLines) {
		int oldStart = 0;
		int oldLength = 0;
		int newStart = 0;
		int newLength = 0;
		if (oldRange[0] > 0)
			oldStart= oldRange[0]-1;	// line number start at 0!
		else
			oldStart= 0;
		oldLength= oldRange[1];
		if (newRange[0] > 0)
			newStart= newRange[0]-1;	// line number start at 0!
		else
			newStart= 0;
		newLength= newRange[1];
		int hunkType = FilePatch2.CHANGE;
		if (!hasContextLines) {
			if (hasLineAdditions && !hasLineDeletions) {
				hunkType = FilePatch2.ADDITION;
			} else if (!hasLineAdditions && hasLineDeletions) {
				hunkType = FilePatch2.DELETION;
			}
		}
		return new Hunk(parent, hunkType, oldStart, oldLength, newStart, newLength, lines.toArray(new String[lines.size()]));
	}

	public Hunk(FilePatch2 parent, int hunkType, int oldStart, int oldLength,
			int newStart, int newLength, String[] lines) {
		this.fParent = parent;
		if (this.fParent != null) {
			this.fParent.add(this);
		}
		this.hunkType = hunkType;
		this.fOldLength = oldLength;
		this.fOldStart = oldStart;
		this.fNewLength = newLength;
		this.fNewStart = newStart;
		this.fLines = lines;
	}

	public Hunk(FilePatch2 parent, Hunk toCopy) {
		this(parent, toCopy.hunkType, toCopy.fOldStart, toCopy.fOldLength, toCopy.fNewStart, toCopy.fNewLength, toCopy.fLines);
	}

	/*
	 * Returns the contents of this hunk.
	 * Each line starts with a control character. Their meaning is as follows:
	 * <ul>
	 * <li>
	 * '+': add the line
	 * <li>
	 * '-': delete the line
	 * <li>
	 * ' ': no change, context line
	 * </ul>
	 */
	public String getContent() {
		StringBuilder sb= new StringBuilder();
		for (String line : this.fLines) {
			sb.append(line.substring(0, LineReader.length(line)));
			sb.append('\n');
		}
		return sb.toString();
	}

	/*
	 * Returns a descriptive String for this hunk.
	 * It is in the form old_start,old_length -> new_start,new_length.
	 */
	String getDescription() {
		StringBuilder sb= new StringBuilder();
		sb.append(Integer.toString(this.fOldStart));
		sb.append(',');
		sb.append(Integer.toString(this.fOldLength));
		sb.append(" -> "); //$NON-NLS-1$
		sb.append(Integer.toString(this.fNewStart));
		sb.append(',');
		sb.append(Integer.toString(this.fNewLength));
		return sb.toString();
	}

	public String getRejectedDescription() {
		StringBuilder sb= new StringBuilder();
		sb.append("@@ -"); //$NON-NLS-1$
		sb.append(Integer.toString(this.fOldStart));
		sb.append(',');
		sb.append(Integer.toString(this.fOldLength));
		sb.append(" +"); //$NON-NLS-1$
		sb.append(Integer.toString(this.fNewStart));
		sb.append(',');
		sb.append(Integer.toString(this.fNewLength));
		sb.append(" @@"); //$NON-NLS-1$
		return sb.toString();
	}

	public int getHunkType(boolean reverse) {
		if (reverse) {
			if (this.hunkType == FilePatch2.ADDITION)
				return FilePatch2.DELETION;
			if (this.hunkType == FilePatch2.DELETION)
				return FilePatch2.ADDITION;
		}
		return this.hunkType;
	}

	void setHunkType(int hunkType) {
		this.hunkType = hunkType;
	}

	public String[] getLines() {
		return this.fLines;
	}

	@Override
	public String[] getUnifiedLines() {
		String[] ret = new String[this.fLines.length];
		System.arraycopy(this.fLines, 0, ret, 0, this.fLines.length);
		return ret;
	}

	/**
	 * Set the parent of this hunk. This method
	 * should only be invoked from {@link FilePatch2#add(Hunk)}
	 * @param diff the parent of this hunk
	 */
	void setParent(FilePatch2 diff) {
		if (this.fParent == diff)
			return;
		if (this.fParent != null)
			this.fParent.remove(this);
		this.fParent = diff;
	}

	public FilePatch2 getParent() {
		return this.fParent;
	}

	/*
	 * Tries to apply the given hunk on the specified lines.
	 * The parameter shift is added to the line numbers given
	 * in the hunk.
	 */
	public boolean tryPatch(PatchConfiguration configuration, List<String> lines, int shift, int fuzz) {
		boolean reverse = configuration.isReversed();
		int pos = getStart(reverse) + shift;
		List<String> contextLines = new ArrayList<>();
		boolean contextLinesMatched = true;
		boolean precedingLinesChecked = false;
		for (String s : this.fLines) {
			Assert.isTrue(s.length() > 0);
			String line = s.substring(1);
			char controlChar = s.charAt(0);

			if (controlChar == ' ') {	// context lines

				if (pos < 0 || pos >= lines.size())
					return false;
				contextLines.add(line);
				if (linesMatch(configuration, line, lines.get(pos))) {
					pos++;
					continue;
				} else if (fuzz > 0) {
					// doesn't match, use the fuzz factor
					contextLinesMatched = false;
					pos++;
					continue;
				}
				return false;
			} else if (isDeletedDelimeter(controlChar, reverse)) {
				// deleted lines

				if (precedingLinesChecked && !contextLinesMatched && contextLines.size() > 0)
					// context lines inside hunk don't match
					return false;

				// check following context lines if exist
				// use the fuzz factor if needed
				if (!precedingLinesChecked
						&& !contextLinesMatched
						&& contextLines.size() >= fuzz
						&& !checkPrecedingContextLines(configuration, lines,
								fuzz, pos, contextLines))
					return false;
				// else if there is less or equal context line to the fuzz
				// factor we ignore them all and treat as matching

				precedingLinesChecked = true;
				contextLines.clear();
				contextLinesMatched = true;

				if (pos < 0 || pos >= lines.size()) // out of the file
					return false;
				if (linesMatch(configuration, line, lines.get(pos))) {
					pos++;
					continue; // line matched, continue with the next one
				}

				// We must remove all lines at once, return false if this
				// fails. In other words, all lines considered for deletion
				// must be found one by one.
				return false;
			} else if (isAddedDelimeter(controlChar, reverse)) {

				if (precedingLinesChecked && !contextLinesMatched && contextLines.size() > 0)
					return false;

				if (!precedingLinesChecked
						&& !contextLinesMatched
						&& contextLines.size() >= fuzz
						&& !checkPrecedingContextLines(configuration, lines,
								fuzz, pos, contextLines))
					return false;

				precedingLinesChecked = true;
				contextLines.clear();
				contextLinesMatched = true;

				// we don't have to do anything more for a 'try'
			} else
				Assert.isTrue(false, "tryPatch: unknown control character: " + controlChar); //$NON-NLS-1$
		}

		// check following context lines if exist
		if (!contextLinesMatched
				&& fuzz > 0
				&& contextLines.size() > fuzz
				&& !checkFollowingContextLines(configuration, lines, fuzz, pos,
						contextLines))
			return false;

		return true;
	}

	private boolean checkPrecedingContextLines(
			PatchConfiguration configuration, List<String> lines, int fuzz, int pos,
			List<String> contextLines) {
		// ignore from the beginning
		for (int j = fuzz; j < contextLines.size(); j++) {
			if (!linesMatch(configuration, contextLines.get(j),
							lines.get(pos - contextLines.size() + j)))
				return false;
		}
		return true;
	}

	private boolean checkFollowingContextLines(
			PatchConfiguration configuration, List<String> lines, int fuzz, int pos,
			List<String> contextLines) {
		if (!contextLines.isEmpty()) {
			// ignore from the end
			for (int j = 0; j < contextLines.size() - fuzz; j++) {
				if (!linesMatch(configuration, contextLines.get(j),
						lines.get(pos - contextLines.size() + j)))
					return false;
			}
		}
		return true;
	}

	public int getStart(boolean after) {
		if (after) {
			return this.fNewStart;
		}
		return this.fOldStart;
	}

	public void setStart(int start, boolean after) {
		if (after) {
			this.fNewStart = start;
		} else {
			this.fOldStart = start;
		}
	}

	public int getLength(boolean after) {
		if (after) {
			return this.fNewLength;
		}
		return this.fOldLength;
	}

	private int getShift(boolean reverse) {
		if (reverse) {
			return this.fOldLength - this.fNewLength;
		}
		return this.fNewLength - this.fOldLength;
	}

	int doPatch(PatchConfiguration configuration, List<String> lines, int shift, int fuzz) {
		boolean reverse = configuration.isReversed();
		int pos = getStart(reverse) + shift;
		List<String> contextLines = new ArrayList<>();
		boolean contextLinesMatched = true;
		boolean precedingLinesChecked = false;
		String lineDelimiter = getLineDelimiter(lines);

		for (String s : this.fLines) {
			Assert.isTrue(s.length() > 0);
			String line= s.substring(1);
			char controlChar= s.charAt(0);
			if (controlChar == ' ') {
				// context lines
				Assert.isTrue(pos < lines.size(), "doPatch: inconsistency in context"); //$NON-NLS-1$
				contextLines.add(line);
				if (linesMatch(configuration, line, lines.get(pos))) {
					pos++;
					continue;
				} else if (fuzz > 0) {
					// doesn't match, use the fuzz factor
					contextLinesMatched = false;
					pos++;
					continue;
				}
				Assert.isTrue(false, "doPatch: context doesn't match"); //$NON-NLS-1$
//					pos++;
			} else if (isDeletedDelimeter(controlChar, reverse)) {
				// deleted lines
				if (precedingLinesChecked && !contextLinesMatched && contextLines.size() > 0)
					// context lines inside hunk don't match
					Assert.isTrue(false, "doPatch: context lines inside hunk don't match"); //$NON-NLS-1$

				// check following context lines if exist
				// use the fuzz factor if needed
				if (!precedingLinesChecked
						&& !contextLinesMatched
						&& contextLines.size() >= fuzz
						&& !checkPrecedingContextLines(configuration, lines,
								fuzz, pos, contextLines))
					Assert.isTrue(false, "doPatch: preceding context lines don't match, even though fuzz factor has been used"); //$NON-NLS-1$
				// else if there is less or equal context line to the fuzz
				// factor we ignore them all and treat as matching

				precedingLinesChecked = true;
				contextLines.clear();
				contextLinesMatched = true;

				lines.remove(pos);
			} else if (isAddedDelimeter(controlChar, reverse)) {
				// added lines
				if (precedingLinesChecked && !contextLinesMatched && contextLines.size() > 0)
					Assert.isTrue(false, "doPatch: context lines inside hunk don't match"); //$NON-NLS-1$

				if (!precedingLinesChecked
						&& !contextLinesMatched
						&& contextLines.size() >= fuzz
						&& !checkPrecedingContextLines(configuration, lines,
								fuzz, pos, contextLines))
					Assert.isTrue(false, "doPatch: preceding context lines don't match, even though fuzz factor has been used"); //$NON-NLS-1$

				precedingLinesChecked = true;
				contextLines.clear();
				contextLinesMatched = true;

				// if the line contains a delimiter, use a proper one
				if (line.length() > LineReader.length(line))
					line = line.substring(0, LineReader.length(line)) + lineDelimiter;

				if (getLength(reverse) == 0 && pos+1 < lines.size())
					lines.add(pos+1, line);
				else
					lines.add(pos, line);
				pos++;
			} else
				Assert.isTrue(false, "doPatch: unknown control character: " + controlChar); //$NON-NLS-1$
		}
		return getShift(reverse);
	}

	private boolean isDeletedDelimeter(char controlChar, boolean reverse) {
		return (!reverse && controlChar == '-') || (reverse && controlChar == '+');
	}

	private boolean isAddedDelimeter(char controlChar, boolean reverse) {
		return (reverse && controlChar == '-') || (!reverse && controlChar == '+');
	}

	/*
	 * Compares two strings.
	 * If fIgnoreWhitespace is true whitespace is ignored.
	 */
	private boolean linesMatch(PatchConfiguration configuration, String line1, String line2) {
		if (configuration.isIgnoreWhitespace())
			return stripWhiteSpace(line1).equals(stripWhiteSpace(line2));
		if (isIgnoreLineDelimiter()) {
			int l1= LineReader.length(line1);
			int l2= LineReader.length(line2);
			if (l1 != l2)
				return false;
			return line1.regionMatches(0, line2, 0, l1);
		}
		return line1.equals(line2);
	}

	private boolean isIgnoreLineDelimiter() {
		return true;
	}

	private String getLineDelimiter(List<String> lines) {
		if (lines.size() > 0) {
			// get a line separator from the file being patched
			String line0 = lines.get(0);
			return line0.substring(LineReader.length(line0));
		} else if (this.fLines.length > 0) {
			// if the file doesn't exist use a line separator from the patch
			return this.fLines[0].substring(LineReader.length(this.fLines[0]));
		}
		return System.getProperty("line.separator"); //$NON-NLS-1$
	}

	/*
	 * Returns the given string with all whitespace characters removed.
	 * Whitespace is defined by <code>Character.isWhitespace(...)</code>.
	 */
	private String stripWhiteSpace(String s) {
		StringBuilder sb= new StringBuilder();
		int l= s.length();
		for (int i= 0; i < l; i++) {
			char c= s.charAt(i);
			if (!Character.isWhitespace(c))
				sb.append(c);
		}
		return sb.toString();
	}

	public String getContents(boolean isAfterState, boolean reverse) {
		StringBuilder result= new StringBuilder();
		for (String line : this.fLines) {
			String rest= line.substring(1);
			char c = line.charAt(0);
			if (c == ' ') {
				result.append(rest);
			} else if (isDeletedDelimeter(c, reverse) && !isAfterState) {
				result.append(rest);
			} else if (isAddedDelimeter(c, reverse) && isAfterState) {
				result.append(rest);
			}
		}
		return result.toString();
	}

	@Override
	public String getLabel() {
		return getDescription();
	}

	@Override
	public int getStartPosition() {
		return getStart(false);
	}

	@Override
	public InputStream getOriginalContents() {
		String contents = getContents(false, false);
		return asInputStream(contents);
	}

	@Override
	public InputStream getPatchedContents() {
		String contents = getContents(true, false);
		return asInputStream(contents);
	}

	private InputStream asInputStream(String contents) {
		String charSet = getCharset();
		return FileDiffResult.asInputStream(contents, charSet);
	}

	void setCharset(String charset) {
		this.charset = charset;
	}

	/**
	 * {@inheritDoc}
	 * @deprecated This method can be called before the first attempt to apply
	 *             the hunk when it is impossible to determine the encoding and
	 *             in this case it always returns null. Please see
	 *             {@link IFilePatchResult#getCharset()} as a proper way to
	 *             obtain charset.
	 */
	@Deprecated
	@Override
	public String getCharset() {
		return this.charset;
	}

}
