/*
 * Copyright (C) 2011, 2015 François Rey <eclipse.org_@_francois_._rey_._name>
 * 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 java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.TreeSet;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.StatusCommand;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.IndexDiff.StageState;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.pgm.internal.CLIText;
import org.eclipse.jgit.pgm.opt.UntrackedFilesHandler;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;
import org.kohsuke.args4j.spi.RestOfArgumentsHandler;

/**
 * Status command
 */
@Command(usage = "usage_Status", common = true)
class Status extends TextBuiltin {

	protected final String statusFileListFormat = CLIText.get().statusFileListFormat;

	protected final String statusFileListFormatWithPrefix = CLIText.get().statusFileListFormatWithPrefix;

	protected final String statusFileListFormatUnmerged = CLIText.get().statusFileListFormatUnmerged;

	@Option(name = "--porcelain", usage = "usage_machineReadableOutput")
	protected boolean porcelain;

	@Option(name = "--untracked-files", aliases = { "-u", "-uno", "-uall" }, usage = "usage_untrackedFilesMode", handler = UntrackedFilesHandler.class)
	protected String untrackedFilesMode = "all"; // default value //$NON-NLS-1$

	@Argument(required = false, index = 0, metaVar = "metaVar_paths")
	@Option(name = "--", metaVar = "metaVar_paths", multiValued = true, handler = RestOfArgumentsHandler.class)
	protected List<String> filterPaths;

	@Override
	protected void run() throws Exception {
		try (Git git = new Git(db)) {
			StatusCommand statusCommand = git.status();
			if (filterPaths != null && filterPaths.size() > 0)
				for (String path : filterPaths)
					statusCommand.addPath(path);
			org.eclipse.jgit.api.Status status = statusCommand.call();
			printStatus(status);
		}
	}

	private void printStatus(org.eclipse.jgit.api.Status status)
			throws IOException {
		if (porcelain)
			printPorcelainStatus(status);
		else
			printLongStatus(status);
	}

	private void printPorcelainStatus(org.eclipse.jgit.api.Status status)
			throws IOException {

		Collection<String> added = status.getAdded();
		Collection<String> changed = status.getChanged();
		Collection<String> removed = status.getRemoved();
		Collection<String> modified = status.getModified();
		Collection<String> missing = status.getMissing();
		Map<String, StageState> conflicting = status.getConflictingStageState();

		// build a sorted list of all paths except untracked and ignored
		TreeSet<String> sorted = new TreeSet<>();
		sorted.addAll(added);
		sorted.addAll(changed);
		sorted.addAll(removed);
		sorted.addAll(modified);
		sorted.addAll(missing);
		sorted.addAll(conflicting.keySet());

		// list each path
		for (String path : sorted) {
			char x = ' ';
			char y = ' ';

			if (added.contains(path))
				x = 'A';
			else if (changed.contains(path))
				x = 'M';
			else if (removed.contains(path))
				x = 'D';

			if (modified.contains(path))
				y = 'M';
			else if (missing.contains(path))
				y = 'D';

			if (conflicting.containsKey(path)) {
				StageState stageState = conflicting.get(path);

				switch (stageState) {
				case BOTH_DELETED:
					x = 'D';
					y = 'D';
					break;
				case ADDED_BY_US:
					x = 'A';
					y = 'U';
					break;
				case DELETED_BY_THEM:
					x = 'U';
					y = 'D';
					break;
				case ADDED_BY_THEM:
					x = 'U';
					y = 'A';
					break;
				case DELETED_BY_US:
					x = 'D';
					y = 'U';
					break;
				case BOTH_ADDED:
					x = 'A';
					y = 'A';
					break;
				case BOTH_MODIFIED:
					x = 'U';
					y = 'U';
					break;
				default:
					throw new IllegalArgumentException("Unknown StageState: " //$NON-NLS-1$
							+ stageState);
				}
			}

			printPorcelainLine(x, y, path);
		}

		// untracked are always at the end of the list
		if ("all".equals(untrackedFilesMode)) { //$NON-NLS-1$
			TreeSet<String> untracked = new TreeSet<>(
					status.getUntracked());
			for (String path : untracked)
				printPorcelainLine('?', '?', path);
		}
	}

	private void printPorcelainLine(char x, char y, String path)
			throws IOException {
		StringBuilder lineBuilder = new StringBuilder();
		lineBuilder.append(x).append(y).append(' ').append(path);
		outw.println(lineBuilder.toString());
	}

	private void printLongStatus(org.eclipse.jgit.api.Status status)
			throws IOException {
		// Print current branch name
		final Ref head = db.exactRef(Constants.HEAD);
		if (head != null && head.isSymbolic()) {
			String branch = Repository.shortenRefName(head.getLeaf().getName());
			outw.println(CLIText.formatLine(MessageFormat.format(
					CLIText.get().onBranch, branch)));
		} else
			outw.println(CLIText.formatLine(CLIText.get().notOnAnyBranch));

		// List changes
		boolean firstHeader = true;

		Collection<String> added = status.getAdded();
		Collection<String> changed = status.getChanged();
		Collection<String> removed = status.getRemoved();
		Collection<String> modified = status.getModified();
		Collection<String> missing = status.getMissing();
		Collection<String> untracked = status.getUntracked();
		Map<String, StageState> unmergedStates = status
				.getConflictingStageState();
		Collection<String> toBeCommitted = new ArrayList<>(added);
		toBeCommitted.addAll(changed);
		toBeCommitted.addAll(removed);
		int nbToBeCommitted = toBeCommitted.size();
		if (nbToBeCommitted > 0) {
			printSectionHeader(CLIText.get().changesToBeCommitted);
			printList(CLIText.get().statusNewFile,
					CLIText.get().statusModified, CLIText.get().statusRemoved,
					toBeCommitted, added, changed, removed);
			firstHeader = false;
		}
		Collection<String> notStagedForCommit = new ArrayList<>(modified);
		notStagedForCommit.addAll(missing);
		int nbNotStagedForCommit = notStagedForCommit.size();
		if (nbNotStagedForCommit > 0) {
			if (!firstHeader)
				printSectionHeader(""); //$NON-NLS-1$
			printSectionHeader(CLIText.get().changesNotStagedForCommit);
			printList(CLIText.get().statusModified,
					CLIText.get().statusRemoved, null, notStagedForCommit,
					modified, missing, null);
			firstHeader = false;
		}
		int nbUnmerged = unmergedStates.size();
		if (nbUnmerged > 0) {
			if (!firstHeader)
				printSectionHeader(""); //$NON-NLS-1$
			printSectionHeader(CLIText.get().unmergedPaths);
			printUnmerged(unmergedStates);
			firstHeader = false;
		}
		int nbUntracked = untracked.size();
		if (nbUntracked > 0 && ("all".equals(untrackedFilesMode))) { //$NON-NLS-1$
			if (!firstHeader)
				printSectionHeader(""); //$NON-NLS-1$
			printSectionHeader(CLIText.get().untrackedFiles);
			printList(untracked);
		}
	}

	protected void printSectionHeader(String pattern, Object... arguments)
			throws IOException {
		if (!porcelain) {
			outw.println(CLIText.formatLine(MessageFormat.format(pattern,
					arguments)));
			if (!pattern.equals("")) //$NON-NLS-1$
				outw.println(CLIText.formatLine("")); //$NON-NLS-1$
			outw.flush();
		}
	}

	protected int printList(Collection<String> list) throws IOException {
		if (!list.isEmpty()) {
			List<String> sortedList = new ArrayList<>(list);
			java.util.Collections.sort(sortedList);
			for (String filename : sortedList) {
				outw.println(CLIText.formatLine(String.format(
						statusFileListFormat, filename)));
			}
			outw.flush();
			return list.size();
		} else
			return 0;
	}

	protected int printList(String status1, String status2, String status3,
			Collection<String> list, Collection<String> set1,
			Collection<String> set2,
			@SuppressWarnings("unused") Collection<String> set3)
			throws IOException {
		List<String> sortedList = new ArrayList<>(list);
		java.util.Collections.sort(sortedList);
		for (String filename : sortedList) {
			String prefix;
			if (set1.contains(filename))
				prefix = status1;
			else if (set2.contains(filename))
				prefix = status2;
			else
				// if (set3.contains(filename))
				prefix = status3;
			outw.println(CLIText.formatLine(String.format(
					statusFileListFormatWithPrefix, prefix, filename)));
			outw.flush();
		}
		return list.size();
	}

	private void printUnmerged(Map<String, StageState> unmergedStates)
			throws IOException {
		List<String> paths = new ArrayList<>(unmergedStates.keySet());
		Collections.sort(paths);
		for (String path : paths) {
			StageState state = unmergedStates.get(path);
			String stateDescription = getStageStateDescription(state);
			outw.println(CLIText.formatLine(String.format(
					statusFileListFormatUnmerged, stateDescription, path)));
			outw.flush();
		}
	}

	private static String getStageStateDescription(StageState stageState) {
		CLIText text = CLIText.get();
		switch (stageState) {
		case BOTH_DELETED:
			return text.statusBothDeleted;
		case ADDED_BY_US:
			return text.statusAddedByUs;
		case DELETED_BY_THEM:
			return text.statusDeletedByThem;
		case ADDED_BY_THEM:
			return text.statusAddedByThem;
		case DELETED_BY_US:
			return text.statusDeletedByUs;
		case BOTH_ADDED:
			return text.statusBothAdded;
		case BOTH_MODIFIED:
			return text.statusBothModified;
		default:
			throw new IllegalArgumentException("Unknown StageState: " //$NON-NLS-1$
					+ stageState);
		}
	}
}
