/*******************************************************************************
 * Copyright (c) 2006, 2018 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
 *******************************************************************************/
package org.eclipse.compare.internal.core.patch;

import java.io.BufferedReader;
import java.io.IOException;
import java.text.ParseException;
import java.util.*;
import java.util.regex.Pattern;

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

import com.ibm.icu.text.DateFormat;
import com.ibm.icu.text.SimpleDateFormat;

public class PatchReader {
	private static final boolean DEBUG= false;

	private static final String DEV_NULL= "/dev/null"; //$NON-NLS-1$

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

	// 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;

	// we recognize the following date/time formats
	private DateFormat[] fDateFormats= new DateFormat[] {
		new SimpleDateFormat("EEE MMM dd kk:mm:ss yyyy"), //$NON-NLS-1$
		new SimpleDateFormat("yyyy/MM/dd kk:mm:ss"), //$NON-NLS-1$
		new SimpleDateFormat("EEE MMM dd kk:mm:ss yyyy", Locale.US) //$NON-NLS-1$
	};

	private boolean fIsWorkspacePatch;
	private boolean fIsGitPatch;
	private DiffProject[] fDiffProjects;
	private FilePatch2[] fDiffs;

	// API for writing new multi-project patch format
	public static final String MULTIPROJECTPATCH_HEADER= "### Eclipse Workspace Patch"; //$NON-NLS-1$

	public static final String MULTIPROJECTPATCH_VERSION= "1.0"; //$NON-NLS-1$

	public static final String MULTIPROJECTPATCH_PROJECT= "#P"; //$NON-NLS-1$

	private static final Pattern GIT_PATCH_PATTERN= Pattern.compile("^diff --git a/.+ b/.+[\r\n]+$"); //$NON-NLS-1$

	/**
	 * Create a patch reader for the default date formats.
	 */
	public PatchReader() {
		// nothing here
	}

	/**
	 * Create a patch reader for the given date formats.
	 *
	 * @param dateFormats
	 *            Array of <code>DateFormat</code>s to be used when
	 *            extracting dates from the patch.
	 */
	public PatchReader(DateFormat[] dateFormats) {
		this();
		this.fDateFormats = dateFormats;
	}

	public void parse(BufferedReader reader) throws IOException {
		List<FilePatch2> diffs= new ArrayList<>();
		HashMap<String, DiffProject> diffProjects= new HashMap<>(4);
		String line= null;
		boolean reread= false;
		String diffArgs= null;
		String fileName= null;
		// no project means this is a single patch,create a placeholder project for now
		// which will be replaced by the target selected by the user in the preview pane
		String projectName= ""; //$NON-NLS-1$
		this.fIsWorkspacePatch= false;
		this.fIsGitPatch = false;

		LineReader lr= new LineReader(reader);
		lr.ignoreSingleCR(); // Don't treat single CRs as line feeds to be consistent with command line patch
		// Test for our format
		line= lr.readLine();
		if (line != null && line.startsWith(PatchReader.MULTIPROJECTPATCH_HEADER)) {
			this.fIsWorkspacePatch= true;
		} else {
			parse(lr, line);
			return;
		}

		// read leading garbage
		while (true) {
			if (!reread)
				line= lr.readLine();
			reread= false;
			if (line == null)
				break;
			if (line.length() < 4)
				continue; // too short

			if (line.startsWith(PatchReader.MULTIPROJECTPATCH_PROJECT)) {
				projectName= line.substring(2).trim();
				continue;
			}

			if (line.startsWith("Index: ")) { //$NON-NLS-1$
				fileName= line.substring(7).trim();
				continue;
			}
			if (line.startsWith("diff")) { //$NON-NLS-1$
				diffArgs= line.substring(4).trim();
				continue;
			}

			if (line.startsWith("--- ")) { //$NON-NLS-1$
				// if there is no current project or
				// the current project doesn't equal the newly parsed project
				// reset the current project to the newly parsed one, create a new DiffProject
				// and add it to the array
				DiffProject diffProject;
				if (!diffProjects.containsKey(projectName)) {
					diffProject= new DiffProject(projectName);
					diffProjects.put(projectName, diffProject);
				} else {
					diffProject= diffProjects.get(projectName);
				}

				line= readUnifiedDiff(diffs, lr, line, diffArgs, fileName, diffProject);
				diffArgs= fileName= null;
				reread= true;
			}
		}

		lr.close();

		this.fDiffProjects= diffProjects.values().toArray(new DiffProject[diffProjects.size()]);
		this.fDiffs = diffs.toArray(new FilePatch2[diffs.size()]);
	}

	protected FilePatch2 createFileDiff(IPath oldPath, long oldDate,
			IPath newPath, long newDate) {
		return new FilePatch2(oldPath, oldDate, newPath, newDate);
	}

	private String readUnifiedDiff(List<FilePatch2> diffs, LineReader lr, String line, String diffArgs, String fileName, DiffProject diffProject) throws IOException {
		List<FilePatch2> newDiffs= new ArrayList<>();
		String nextLine= readUnifiedDiff(newDiffs, lr, line, diffArgs, fileName);
		for (Iterator<FilePatch2> iter= newDiffs.iterator(); iter.hasNext();) {
			FilePatch2 diff= iter.next();
			diffProject.add(diff);
			diffs.add(diff);
		}
		return nextLine;
	}

	public void parse(LineReader lr, String line) throws IOException {
		List<FilePatch2> diffs= new ArrayList<>();
		boolean reread= false;
		String diffArgs= null;
		String fileName= null;
		List<String> headerLines = new ArrayList<>();
		boolean foundDiff= false;

		// read leading garbage
		reread= line!=null;
		while (true) {
			if (!reread)
				line= lr.readLine();
			reread= false;
			if (line == null)
				break;

			// remember some infos
			if (line.startsWith("Index: ")) { //$NON-NLS-1$
				fileName= line.substring(7).trim();
			} else if (line.startsWith("diff")) { //$NON-NLS-1$
				if (!foundDiff && GIT_PATCH_PATTERN.matcher(line).matches())
					this.fIsGitPatch= true;
				foundDiff= true;
				diffArgs= line.substring(4).trim();
			} else if (line.startsWith("--- ")) { //$NON-NLS-1$
				line= readUnifiedDiff(diffs, lr, line, diffArgs, fileName);
				if (!headerLines.isEmpty())
					setHeader(diffs.get(diffs.size() - 1), headerLines);
				diffArgs= fileName= null;
				reread= true;
			} else if (line.startsWith("*** ")) { //$NON-NLS-1$
				line= readContextDiff(diffs, lr, line, diffArgs, fileName);
				if (!headerLines.isEmpty())
					setHeader(diffs.get(diffs.size() - 1), headerLines);
				diffArgs= fileName= null;
				reread= true;
			}

			// Any lines we read here are header lines.
			// However, if reread is set, we will add them to the header on the next pass through
			if (!reread) {
				headerLines.add(line);
			}
		}

		lr.close();

		this.fDiffs = diffs.toArray(new FilePatch2[diffs.size()]);
	}

	private void setHeader(FilePatch2 diff, List<String> headerLines) {
		String header = LineReader.createString(false, headerLines);
		diff.setHeader(header);
		headerLines.clear();
	}

	/*
	 * Returns the next line that does not belong to this diff
	 */
	protected String readUnifiedDiff(List<FilePatch2> diffs, LineReader reader, String line, String args, String fileName) throws IOException {

		String[] oldArgs= split(line.substring(4));

		// read info about new file
		line= reader.readLine();
		if (line == null || !line.startsWith("+++ ")) //$NON-NLS-1$
			return line;

		String[] newArgs= split(line.substring(4));

		FilePatch2 diff = createFileDiff(extractPath(oldArgs, 0, fileName),
				extractDate(oldArgs, 1), extractPath(newArgs, 0, fileName),
				extractDate(newArgs, 1));
		diffs.add(diff);

		int[] oldRange= new int[2];
		int[] newRange= new int[2];
		int remainingOld= -1; // remaining old lines for current hunk
		int remainingNew= -1; // remaining new lines for current hunk
		List<String> lines= new ArrayList<>();

		boolean encounteredPlus = false;
		boolean encounteredMinus = false;
		boolean encounteredSpace = false;

		try {
			// read lines of hunk
			while (true) {

				line= reader.readLine();
				if (line == null)
					return null;

				if (reader.lineContentLength(line) == 0) {
					//System.out.println("Warning: found empty line in hunk; ignored");
					//lines.add(' ' + line);
					continue;
				}

				char c= line.charAt(0);
				if (remainingOld == 0 && remainingNew == 0 && c != '@' && c != '\\') {
					return line;
				}

				switch (c) {
					case '@':
						if (line.startsWith("@@ ")) { //$NON-NLS-1$
							// flush old hunk
							if (lines.size() > 0) {
								Hunk.createHunk(diff, oldRange, newRange, lines, encounteredPlus, encounteredMinus, encounteredSpace);
								lines.clear();
							}

							// format: @@ -oldStart,oldLength +newStart,newLength @@
							extractPair(line, '-', oldRange);
							extractPair(line, '+', newRange);
							remainingOld= oldRange[1];
							remainingNew= newRange[1];
							continue;
						}
						break;
					case ' ':
						encounteredSpace= true;
						remainingOld--;
						remainingNew--;
						lines.add(line);
						continue;
					case '+':
						encounteredPlus= true;
						remainingNew--;
						lines.add(line);
						continue;
					case '-':
						encounteredMinus= true;
						remainingOld--;
						lines.add(line);
						continue;
					case '\\':
						if (line.indexOf("newline at end") > 0) { //$NON-NLS-1$
							int lastIndex= lines.size();
							if (lastIndex > 0) {
								line= lines.get(lastIndex - 1);
								int end= line.length() - 1;
								char lc= line.charAt(end);
								if (lc == '\n') {
									end--;
									if (end > 0 && line.charAt(end) == '\r')
										end--;
								} else if (lc == '\r') {
									end--;
								}
								line= line.substring(0, end + 1);
								lines.set(lastIndex - 1, line);
							}
							continue;
						}
						break;
					case '#':
						break;
					case 'I':
						if (line.indexOf("Index:") == 0) //$NON-NLS-1$
							break;
						//$FALL-THROUGH$
					case 'd':
						if (line.indexOf("diff ") == 0) //$NON-NLS-1$
							break;
						//$FALL-THROUGH$
					case 'B':
						if (line.indexOf("Binary files differ") == 0) //$NON-NLS-1$
							break;
						//$FALL-THROUGH$
					default:
						break;
				}
				return line;
			}
		} finally {
			if (lines.size() > 0)
				Hunk.createHunk(diff, oldRange, newRange, lines, encounteredPlus, encounteredMinus, encounteredSpace);
		}
	}

	/*
	 * Returns the next line that does not belong to this diff
	 */
	private String readContextDiff(List<FilePatch2> diffs, LineReader reader, String line, String args, String fileName) throws IOException {

		String[] oldArgs= split(line.substring(4));

		// read info about new file
		line= reader.readLine();
		if (line == null || !line.startsWith("--- ")) //$NON-NLS-1$
			return line;

		String[] newArgs= split(line.substring(4));

		FilePatch2 diff = createFileDiff(extractPath(oldArgs, 0, fileName),
				extractDate(oldArgs, 1), extractPath(newArgs, 0, fileName),
				extractDate(newArgs, 1));
		diffs.add(diff);

		int[] oldRange= new int[2];
		int[] newRange= new int[2];
		List<String> oldLines= new ArrayList<>();
		List<String> newLines= new ArrayList<>();
		List<String> lines= oldLines;


		boolean encounteredPlus = false;
		boolean encounteredMinus = false;
		boolean encounteredSpace = false;

		try {
			// read lines of hunk
			while (true) {

				line= reader.readLine();
				if (line == null)
					return line;

				int l= line.length();
				if (l == 0)
					continue;
				if (l > 1) {
					switch (line.charAt(0)) {
					case '*':
						if (line.startsWith("***************")) {	// new hunk //$NON-NLS-1$
							// flush old hunk
							if (oldLines.size() > 0 || newLines.size() > 0) {
								Hunk.createHunk(diff, oldRange, newRange, unifyLines(oldLines, newLines), encounteredPlus, encounteredMinus, encounteredSpace);
								oldLines.clear();
								newLines.clear();
							}
							continue;
						}
						if (line.startsWith("*** ")) {	// old range //$NON-NLS-1$
							// format: *** oldStart,oldEnd ***
							extractPair(line, ' ', oldRange);
							if (oldRange[0] == 0) {
								oldRange[1] = 0; // In case of the file addition
							} else {
								oldRange[1] = oldRange[1] - oldRange[0] + 1;
							}
							lines= oldLines;
							continue;
						}
						break;
					case ' ':	// context line
						if (line.charAt(1) == ' ') {
							lines.add(line);
							continue;
						}
						break;
					case '+':	// addition
						if (line.charAt(1) == ' ') {
							encounteredPlus = true;
							lines.add(line);
							continue;
						}
						break;
					case '!':	// change
						if (line.charAt(1) == ' ') {
							encounteredSpace = true;
							lines.add(line);
							continue;
						}
						break;
					case '-':
						if (line.charAt(1) == ' ') {	// deletion
							encounteredMinus = true;
							lines.add(line);
							continue;
						}
						if (line.startsWith("--- ")) {	// new range //$NON-NLS-1$
							// format: *** newStart,newEnd ***
							extractPair(line, ' ', newRange);
							if (newRange[0] == 0) {
								newRange[1] = 0; // In case of the file removal
							} else {
								newRange[1] = newRange[1] - newRange[0] + 1;
							}
							lines= newLines;
							continue;
						}
						break;
					default:
						break;
					}
				}
				return line;
			}
		} finally {
			// flush last hunk
			if (oldLines.size() > 0 || newLines.size() > 0)
				Hunk.createHunk(diff, oldRange, newRange, unifyLines(oldLines, newLines), encounteredPlus, encounteredMinus, encounteredSpace);
		}
	}

	/*
	 * Creates a List of lines in the unified format from
	 * two Lists of lines in the 'classic' format.
	 */
	private List<String> unifyLines(List<String> oldLines, List<String> newLines) {
		List<String> result= new ArrayList<>();

		String[] ol= oldLines.toArray(new String[oldLines.size()]);
		String[] nl= newLines.toArray(new String[newLines.size()]);

		int oi= 0, ni= 0;

		while (true) {

			char oc= 0;
			String o= null;
			if (oi < ol.length) {
				o= ol[oi];
				oc= o.charAt(0);
			}

			char nc= 0;
			String n= null;
			if (ni < nl.length) {
				n= nl[ni];
				nc= n.charAt(0);
			}

			// EOF
			if (oc == 0 && nc == 0)
				break;

			// deletion in old
			if (oc == '-') {
				do {
					result.add('-' + o.substring(2));
					oi++;
					if (oi >= ol.length)
						break;
					o= ol[oi];
				} while (o.charAt(0) == '-');
				continue;
			}

			// addition in new
			if (nc == '+') {
				do {
					result.add('+' + n.substring(2));
					ni++;
					if (ni >= nl.length)
						break;
					n= nl[ni];
				} while (n.charAt(0) == '+');
				continue;
			}

			// differing lines on both sides
			if (oc == '!' && nc == '!') {
				// remove old
				do {
					result.add('-' + o.substring(2));
					oi++;
					if (oi >= ol.length)
						break;
					o= ol[oi];
				} while (o.charAt(0) == '!');

				// add new
				do {
					result.add('+' + n.substring(2));
					ni++;
					if (ni >= nl.length)
						break;
					n= nl[ni];
				} while (n.charAt(0) == '!');

				continue;
			}

			// context lines
			if (oc == ' ' && nc == ' ') {
				do {
					Assert.isTrue(o.equals(n), "non matching context lines"); //$NON-NLS-1$
					result.add(' ' + o.substring(2));
					oi++;
					ni++;
					if (oi >= ol.length || ni >= nl.length)
						break;
					o= ol[oi];
					n= nl[ni];
				} while (o.charAt(0) == ' ' && n.charAt(0) == ' ');
				continue;
			}

			if (oc == ' ') {
				do {
					result.add(' ' + o.substring(2));
					oi++;
					if (oi >= ol.length)
						break;
					o= ol[oi];
				} while (o.charAt(0) == ' ');
				continue;
			}

			if (nc == ' ') {
				do {
					result.add(' ' + n.substring(2));
					ni++;
					if (ni >= nl.length)
						break;
					n= nl[ni];
				} while (n.charAt(0) == ' ');
				continue;
			}

			Assert.isTrue(false, "unexpected char <" + oc + "> <" + nc + ">"); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
		}

		return result;
	}

	/*
	 * @return the parsed time/date in milliseconds or IFilePatch.DATE_UNKNOWN
	 * (0) on error
	 */
	private long extractDate(String[] args, int n) {
		if (n < args.length) {
			String line= args[n];
			for (int i= 0; i < this.fDateFormats.length; i++) {
				this.fDateFormats[i].setLenient(true);
				try {
					Date date= this.fDateFormats[i].parse(line);
					return date.getTime();
				} catch (ParseException ex) {
					// silently ignored
				}
			}
			// System.err.println("can't parse date: <" + line + ">");
		}
		return IFilePatch2.DATE_UNKNOWN;
	}

	/*
	 * Returns null if file name is "/dev/null".
	 */
	private IPath extractPath(String[] args, int n, String path2) {
		if (n < args.length) {
			String path= args[n];
			if (DEV_NULL.equals(path))
				return null;
			int pos= path.lastIndexOf(':');
			if (pos >= 0)
				path= path.substring(0, pos);
			if (path2 != null && !path2.equals(path)) {
				if (DEBUG) System.out.println("path mismatch: " + path2); //$NON-NLS-1$
				path= path2;
			}
			return new Path(path);
		}
		return null;
	}

	/*
	 * Tries to extract two integers separated by a comma.
	 * The parsing of the line starts at the position after
	 * the first occurrence of the given character start an ends
	 * at the first blank (or the end of the line).
	 * If only a single number is found this is assumed to be the start of a one line range.
	 * If an error occurs the range -1,-1 is returned.
	 */
	private void extractPair(String line, char start, int[] pair) {
		pair[0]= pair[1]= -1;
		int startPos= line.indexOf(start);
		if (startPos < 0) {
			if (DEBUG) System.out.println("parsing error in extractPair: couldn't find \'" + start + "\'"); //$NON-NLS-1$ //$NON-NLS-2$
			return;
		}
		line= line.substring(startPos+1);
		int endPos= line.indexOf(' ');
		if (endPos < 0) {
			if (DEBUG) System.out.println("parsing error in extractPair: couldn't find end blank"); //$NON-NLS-1$
			return;
		}
		line= line.substring(0, endPos);
		int comma= line.indexOf(',');
		if (comma >= 0) {
			pair[0]= Integer.parseInt(line.substring(0, comma));
			pair[1]= Integer.parseInt(line.substring(comma+1));
		} else {	// abbreviated form for one line patch
			pair[0]= Integer.parseInt(line);
			pair[1]= 1;
		}
	}

	/*
	 * Breaks the given string into tab separated substrings.
	 * Leading and trailing whitespace is removed from each token.
	 */
	private String[] split(String line) {
		List<String> l= new ArrayList<>();
		StringTokenizer st= new StringTokenizer(line, "\t"); //$NON-NLS-1$
		while (st.hasMoreElements()) {
			String token= st.nextToken().trim();
			if (token.length() > 0)
 				l.add(token);
		}
		return l.toArray(new String[l.size()]);
	}

	public boolean isWorkspacePatch() {
		return this.fIsWorkspacePatch;
	}

	public boolean isGitPatch() {
		return this.fIsGitPatch;
	}

	public DiffProject[] getDiffProjects() {
		return this.fDiffProjects;
	}

	public FilePatch2[] getDiffs() {
		return this.fDiffs;
	}

	public FilePatch2[] getAdjustedDiffs() {
		if (!isWorkspacePatch() || this.fDiffs.length == 0)
			return this.fDiffs;
		List<FilePatch2> result = new ArrayList<>();
		for (int i = 0; i < this.fDiffs.length; i++) {
			FilePatch2 diff = this.fDiffs[i];
			result.add(diff.asRelativeDiff());
		}
		return result.toArray(new FilePatch2[result.size()]);
	}

}
