/*
 * Copyright (C) 2011, Google Inc.
 * Copyright (C) 2009, Christian Halstrick <christian.halstrick@sap.com>
 * Copyright (C) 2009, Johannes E. Schindelin
 * Copyright (C) 2009, Johannes Schindelin <johannes.schindelin@gmx.de>
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.pgm;

import static java.lang.Integer.valueOf;
import static java.lang.Long.valueOf;
import static org.eclipse.jgit.lib.Constants.OBJECT_ID_STRING_LENGTH;

import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

import org.eclipse.jgit.blame.BlameGenerator;
import org.eclipse.jgit.blame.BlameResult;
import org.eclipse.jgit.diff.RawText;
import org.eclipse.jgit.diff.RawTextComparator;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.pgm.internal.CLIText;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevFlag;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;

@Command(common = false, usage = "usage_Blame")
class Blame extends TextBuiltin {
	private RawTextComparator comparator = RawTextComparator.DEFAULT;

	@Option(name = "-w", usage = "usage_ignoreWhitespace")
	void ignoreAllSpace(@SuppressWarnings("unused") boolean on) {
		comparator = RawTextComparator.WS_IGNORE_ALL;
	}

	@Option(name = "--abbrev", metaVar = "metaVar_n", usage = "usage_abbrevCommits")
	private int abbrev;

	@Option(name = "-l", usage = "usage_blameLongRevision")
	private boolean showLongRevision;

	@Option(name = "-t", usage = "usage_blameRawTimestamp")
	private boolean showRawTimestamp;

	@Option(name = "-b", usage = "usage_blameShowBlankBoundary")
	private boolean showBlankBoundary;

	@Option(name = "-s", usage = "usage_blameSuppressAuthor")
	private boolean noAuthor;

	@Option(name = "--show-email", aliases = { "-e" }, usage = "usage_blameShowEmail")
	private boolean showAuthorEmail;

	@Option(name = "--show-name", aliases = { "-f" }, usage = "usage_blameShowSourcePath")
	private boolean showSourcePath;

	@Option(name = "--show-number", aliases = { "-n" }, usage = "usage_blameShowSourceLine")
	private boolean showSourceLine;

	@Option(name = "--root", usage = "usage_blameShowRoot")
	private boolean root;

	@Option(name = "-L", metaVar = "metaVar_blameL", usage = "usage_blameRange")
	private String rangeString;

	@Option(name = "--reverse", metaVar = "metaVar_blameReverse", usage = "usage_blameReverse")
	private List<RevCommit> reverseRange = new ArrayList<>(2);

	@Argument(index = 0, required = false, metaVar = "metaVar_revision")
	private String revision;

	@Argument(index = 1, required = false, metaVar = "metaVar_file")
	private String file;

	private ObjectReader reader;

	private final Map<RevCommit, String> abbreviatedCommits = new HashMap<>();

	private SimpleDateFormat dateFmt;

	private int begin;

	private int end;

	private BlameResult blame;

	/** {@inheritDoc} */
	@Override
	protected void run() throws Exception {
		if (file == null) {
			if (revision == null)
				throw die(CLIText.get().fileIsRequired);
			file = revision;
			revision = null;
		}

		boolean autoAbbrev = abbrev == 0;
		if (abbrev == 0)
			abbrev = db.getConfig().getInt("core", "abbrev", 7); //$NON-NLS-1$ //$NON-NLS-2$
		if (!showBlankBoundary)
			root = db.getConfig().getBoolean("blame", "blankboundary", false); //$NON-NLS-1$ //$NON-NLS-2$
		if (!root)
			root = db.getConfig().getBoolean("blame", "showroot", false); //$NON-NLS-1$ //$NON-NLS-2$

		if (showRawTimestamp)
			dateFmt = new SimpleDateFormat("ZZZZ"); //$NON-NLS-1$
		else
			dateFmt = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss ZZZZ"); //$NON-NLS-1$

		reader = db.newObjectReader();
		try (BlameGenerator generator = new BlameGenerator(db, file)) {
			RevFlag scanned = generator.newFlag("SCANNED"); //$NON-NLS-1$
			generator.setTextComparator(comparator);

			if (!reverseRange.isEmpty()) {
				RevCommit rangeStart = null;
				List<RevCommit> rangeEnd = new ArrayList<>(2);
				for (RevCommit c : reverseRange) {
					if (c.has(RevFlag.UNINTERESTING))
						rangeStart = c;
					else
						rangeEnd.add(c);
				}
				generator.reverse(rangeStart, rangeEnd);
			} else if (revision != null) {
				generator.push(null, db.resolve(revision + "^{commit}")); //$NON-NLS-1$
			} else {
				generator.push(null, db.resolve(Constants.HEAD));
				if (!db.isBare()) {
					DirCache dc = db.readDirCache();
					int entry = dc.findEntry(file);
					if (0 <= entry)
						generator.push(null, dc.getEntry(entry).getObjectId());

					File inTree = new File(db.getWorkTree(), file);
					if (db.getFS().isFile(inTree))
						generator.push(null, new RawText(inTree));
				}
			}

			blame = BlameResult.create(generator);
			begin = 0;
			end = blame.getResultContents().size();
			if (rangeString != null)
				parseLineRangeOption();
			blame.computeRange(begin, end);

			int authorWidth = 8;
			int dateWidth = 8;
			int pathWidth = 1;
			int maxSourceLine = 1;
			for (int line = begin; line < end; line++) {
				RevCommit c = blame.getSourceCommit(line);
				if (c != null && !c.has(scanned)) {
					c.add(scanned);
					if (autoAbbrev)
						abbrev = Math.max(abbrev, uniqueAbbrevLen(c));
					authorWidth = Math.max(authorWidth, author(line).length());
					dateWidth = Math.max(dateWidth, date(line).length());
					pathWidth = Math.max(pathWidth, path(line).length());
				}
				while (line + 1 < end && blame.getSourceCommit(line + 1) == c)
					line++;
				maxSourceLine = Math.max(maxSourceLine, blame.getSourceLine(line));
			}

			String pathFmt = MessageFormat.format(" %{0}s", valueOf(pathWidth)); //$NON-NLS-1$
			String numFmt = MessageFormat.format(" %{0}d", //$NON-NLS-1$
					valueOf(1 + (int) Math.log10(maxSourceLine + 1)));
			String lineFmt = MessageFormat.format(" %{0}d) ", //$NON-NLS-1$
					valueOf(1 + (int) Math.log10(end + 1)));
			String authorFmt = MessageFormat.format(" (%-{0}s %{1}s", //$NON-NLS-1$
					valueOf(authorWidth), valueOf(dateWidth));

			for (int line = begin; line < end;) {
				RevCommit c = blame.getSourceCommit(line);
				String commit = abbreviate(c);
				String author = null;
				String date = null;
				if (!noAuthor) {
					author = author(line);
					date = date(line);
				}
				do {
					outw.print(commit);
					if (showSourcePath)
						outw.format(pathFmt, path(line));
					if (showSourceLine)
						outw.format(numFmt, valueOf(blame.getSourceLine(line) + 1));
					if (!noAuthor)
						outw.format(authorFmt, author, date);
					outw.format(lineFmt, valueOf(line + 1));
					outw.flush();
					blame.getResultContents().writeLine(outs, line);
					outs.flush();
					outw.print('\n');
				} while (++line < end && blame.getSourceCommit(line) == c);
			}
		} finally {
			reader.close();
		}
	}

	private int uniqueAbbrevLen(RevCommit commit) throws IOException {
		return reader.abbreviate(commit, abbrev).length();
	}

	private void parseLineRangeOption() {
		String beginStr, endStr;
		if (rangeString.startsWith("/")) { //$NON-NLS-1$
			int c = rangeString.indexOf("/,", 1); //$NON-NLS-1$
			if (c < 0) {
				beginStr = rangeString;
				endStr = String.valueOf(end);
			} else {
				beginStr = rangeString.substring(0, c);
				endStr = rangeString.substring(c + 2);
			}

		} else {
			int c = rangeString.indexOf(',');
			if (c < 0) {
				beginStr = rangeString;
				endStr = String.valueOf(end);
			} else if (c == 0) {
				beginStr = "0"; //$NON-NLS-1$
				endStr = rangeString.substring(1);
			} else {
				beginStr = rangeString.substring(0, c);
				endStr = rangeString.substring(c + 1);
			}
		}

		if (beginStr.equals("")) //$NON-NLS-1$
			begin = 0;
		else if (beginStr.startsWith("/")) //$NON-NLS-1$
			begin = findLine(0, beginStr);
		else
			begin = Math.max(0, Integer.parseInt(beginStr) - 1);

		if (endStr.equals("")) //$NON-NLS-1$
			end = blame.getResultContents().size();
		else if (endStr.startsWith("/")) //$NON-NLS-1$
			end = findLine(begin, endStr);
		else if (endStr.startsWith("-")) //$NON-NLS-1$
			end = begin + Integer.parseInt(endStr);
		else if (endStr.startsWith("+")) //$NON-NLS-1$
			end = begin + Integer.parseInt(endStr.substring(1));
		else
			end = Math.max(0, Integer.parseInt(endStr) - 1);
	}

	private int findLine(int b, String regex) {
		String re = regex.substring(1, regex.length() - 1);
		if (!re.startsWith("^")) //$NON-NLS-1$
			re = ".*" + re; //$NON-NLS-1$
		if (!re.endsWith("$")) //$NON-NLS-1$
			re = re + ".*"; //$NON-NLS-1$
		Pattern p = Pattern.compile(re);
		RawText text = blame.getResultContents();
		for (int line = b; line < text.size(); line++) {
			if (p.matcher(text.getString(line)).matches())
				return line;
		}
		return b;
	}

	private String path(int line) {
		String p = blame.getSourcePath(line);
		return p != null ? p : ""; //$NON-NLS-1$
	}

	private String author(int line) {
		PersonIdent author = blame.getSourceAuthor(line);
		if (author == null)
			return ""; //$NON-NLS-1$
		String name = showAuthorEmail ? author.getEmailAddress() : author
				.getName();
		return name != null ? name : ""; //$NON-NLS-1$
	}

	private String date(int line) {
		if (blame.getSourceCommit(line) == null)
			return ""; //$NON-NLS-1$

		PersonIdent author = blame.getSourceAuthor(line);
		if (author == null)
			return ""; //$NON-NLS-1$

		dateFmt.setTimeZone(author.getTimeZone());
		if (!showRawTimestamp)
			return dateFmt.format(author.getWhen());
		return String.format("%d %s", //$NON-NLS-1$
				valueOf(author.getWhen().getTime() / 1000L),
				dateFmt.format(author.getWhen()));
	}

	private String abbreviate(RevCommit commit) throws IOException {
		String r = abbreviatedCommits.get(commit);
		if (r != null)
			return r;

		if (showBlankBoundary && commit.getParentCount() == 0)
			commit = null;

		if (commit == null) {
			int len = showLongRevision ? OBJECT_ID_STRING_LENGTH : (abbrev + 1);
			StringBuilder b = new StringBuilder(len);
			for (int i = 0; i < len; i++)
				b.append(' ');
			r = b.toString();

		} else if (!root && commit.getParentCount() == 0) {
			if (showLongRevision)
				r = "^" + commit.name().substring(0, OBJECT_ID_STRING_LENGTH - 1); //$NON-NLS-1$
			else
				r = "^" + reader.abbreviate(commit, abbrev).name(); //$NON-NLS-1$
		} else {
			if (showLongRevision)
				r = commit.name();
			else
				r = reader.abbreviate(commit, abbrev + 1).name();
		}

		abbreviatedCommits.put(commit, r);
		return r;
	}
}
