/*
 * Copyright (C) 2007-2008, Charles O'Farrell <charleso@charleso.org>
 * 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.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ListBranchCommand;
import org.eclipse.jgit.api.ListBranchCommand.ListMode;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefComparator;
import org.eclipse.jgit.lib.RefRename;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.pgm.internal.CLIText;
import org.eclipse.jgit.pgm.opt.OptionWithValuesListHandler;
import org.eclipse.jgit.revwalk.RevWalk;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;

@Command(common = true, usage = "usage_listCreateOrDeleteBranches")
class Branch extends TextBuiltin {

	private String otherBranch;
	private boolean createForce;
	private boolean rename;

	@Option(name = "--remote", aliases = { "-r" }, usage = "usage_actOnRemoteTrackingBranches")
	private boolean remote = false;

	@Option(name = "--all", aliases = { "-a" }, usage = "usage_listBothRemoteTrackingAndLocalBranches")
	private boolean all = false;

	@Option(name = "--contains", metaVar = "metaVar_commitish", usage = "usage_printOnlyBranchesThatContainTheCommit")
	private String containsCommitish;

	private List<String> delete;

	/**
	 * Delete branches
	 *
	 * @param names
	 *            a {@link java.util.List} of branch names.
	 */
	@Option(name = "--delete", aliases = {
			"-d" }, metaVar = "metaVar_branchNames", usage = "usage_deleteFullyMergedBranch", handler = OptionWithValuesListHandler.class)
	public void delete(List<String> names) {
		if (names.isEmpty()) {
			throw die(CLIText.get().branchNameRequired);
		}
		delete = names;
	}

	private List<String> deleteForce;

	/**
	 * Forcefully delete branches
	 *
	 * @param names
	 *            a {@link java.util.List} of branch names.
	 */
	@Option(name = "--delete-force", aliases = {
			"-D" }, metaVar = "metaVar_branchNames", usage = "usage_deleteBranchEvenIfNotMerged", handler = OptionWithValuesListHandler.class)
	public void deleteForce(List<String> names) {
		if (names.isEmpty()) {
			throw die(CLIText.get().branchNameRequired);
		}
		deleteForce = names;
	}

	/**
	 * Forcefully create a list of branches
	 *
	 * @param branchAndStartPoint
	 *            a branch name and a start point
	 */
	@Option(name = "--create-force", aliases = {
			"-f" }, metaVar = "metaVar_branchAndStartPoint", usage = "usage_forceCreateBranchEvenExists", handler = OptionWithValuesListHandler.class)
	public void createForce(List<String> branchAndStartPoint) {
		createForce = true;
		if (branchAndStartPoint.isEmpty()) {
			throw die(CLIText.get().branchNameRequired);
		}
		if (branchAndStartPoint.size() > 2) {
			throw die(CLIText.get().tooManyRefsGiven);
		}
		if (branchAndStartPoint.size() == 1) {
			branch = branchAndStartPoint.get(0);
		} else {
			branch = branchAndStartPoint.get(0);
			otherBranch = branchAndStartPoint.get(1);
		}
	}

	/**
	 * Move or rename a branch
	 *
	 * @param currentAndNew
	 *            the current and the new branch name
	 */
	@Option(name = "--move", aliases = {
			"-m" }, metaVar = "metaVar_oldNewBranchNames", usage = "usage_moveRenameABranch", handler = OptionWithValuesListHandler.class)
	public void moveRename(List<String> currentAndNew) {
		rename = true;
		if (currentAndNew.isEmpty()) {
			throw die(CLIText.get().branchNameRequired);
		}
		if (currentAndNew.size() > 2) {
			throw die(CLIText.get().tooManyRefsGiven);
		}
		if (currentAndNew.size() == 1) {
			branch = currentAndNew.get(0);
		} else {
			branch = currentAndNew.get(0);
			otherBranch = currentAndNew.get(1);
		}
	}

	@Option(name = "--verbose", aliases = { "-v" }, usage = "usage_beVerbose")
	private boolean verbose = false;

	@Argument(metaVar = "metaVar_name")
	private String branch;

	private final Map<String, Ref> printRefs = new LinkedHashMap<>();

	/** Only set for verbose branch listing at-the-moment */
	private RevWalk rw;

	private int maxNameLength;

	/** {@inheritDoc} */
	@Override
	protected void run() {
		try {
			if (delete != null || deleteForce != null) {
				if (delete != null) {
					delete(delete, false);
				}
				if (deleteForce != null) {
					delete(deleteForce, true);
				}
				return;
			}
			if (rename) {
				String src, dst;
				if (otherBranch == null) {
					final Ref head = db.exactRef(Constants.HEAD);
					if (head != null && head.isSymbolic()) {
						src = head.getLeaf().getName();
					} else {
						throw die(CLIText.get().cannotRenameDetachedHEAD);
					}
					dst = branch;
				} else {
					src = branch;
					final Ref old = db.findRef(src);
					if (old == null) {
						throw die(MessageFormat.format(CLIText.get().doesNotExist, src));
					}
					if (!old.getName().startsWith(Constants.R_HEADS)) {
						throw die(MessageFormat.format(CLIText.get().notABranch, src));
					}
					src = old.getName();
					dst = otherBranch;
				}

				if (!dst.startsWith(Constants.R_HEADS)) {
					dst = Constants.R_HEADS + dst;
				}
				if (!Repository.isValidRefName(dst)) {
					throw die(MessageFormat.format(CLIText.get().notAValidRefName, dst));
				}

				RefRename r = db.renameRef(src, dst);
				if (r.rename() != Result.RENAMED) {
					throw die(MessageFormat.format(CLIText.get().cannotBeRenamed, src));
				}

			} else if (createForce || branch != null) {
				String newHead = branch;
				String startBranch;
				if (createForce) {
					startBranch = otherBranch;
				} else {
					startBranch = Constants.HEAD;
				}
				Ref startRef = db.findRef(startBranch);
				ObjectId startAt = db.resolve(startBranch + "^0"); //$NON-NLS-1$
				if (startRef != null) {
					startBranch = startRef.getName();
				} else if (startAt != null) {
					startBranch = startAt.name();
				} else {
					throw die(MessageFormat.format(
							CLIText.get().notAValidCommitName, startBranch));
				}
				startBranch = Repository.shortenRefName(startBranch);
				String newRefName = newHead;
				if (!newRefName.startsWith(Constants.R_HEADS)) {
					newRefName = Constants.R_HEADS + newRefName;
				}
				if (!Repository.isValidRefName(newRefName)) {
					throw die(MessageFormat.format(CLIText.get().notAValidRefName, newRefName));
				}
				if (!createForce && db.resolve(newRefName) != null) {
					throw die(MessageFormat.format(CLIText.get().branchAlreadyExists, newHead));
				}
				RefUpdate updateRef = db.updateRef(newRefName);
				updateRef.setNewObjectId(startAt);
				updateRef.setForceUpdate(createForce);
				updateRef.setRefLogMessage(MessageFormat.format(CLIText.get().branchCreatedFrom, startBranch), false);
				Result update = updateRef.update();
				if (update == Result.REJECTED) {
					throw die(MessageFormat.format(CLIText.get().couldNotCreateBranch, newHead, update.toString()));
				}
			} else {
				if (verbose) {
					rw = new RevWalk(db);
				}
				list();
			}
		} catch (IOException | GitAPIException e) {
			throw die(e.getMessage(), e);
		}
	}

	private void list() throws IOException, GitAPIException {
		Ref head = db.exactRef(Constants.HEAD);
		// This can happen if HEAD is stillborn
		if (head != null) {
			String current = head.getLeaf().getName();
			try (Git git = new Git(db)) {
				ListBranchCommand command = git.branchList();
				if (all)
					command.setListMode(ListMode.ALL);
				else if (remote)
					command.setListMode(ListMode.REMOTE);

				if (containsCommitish != null)
					command.setContains(containsCommitish);

				List<Ref> refs = command.call();
				for (Ref ref : refs) {
					if (ref.getName().equals(Constants.HEAD))
						addRef("(no branch)", head); //$NON-NLS-1$
				}

				addRefs(refs, Constants.R_HEADS);
				addRefs(refs, Constants.R_REMOTES);

				try (ObjectReader reader = db.newObjectReader()) {
					for (Entry<String, Ref> e : printRefs.entrySet()) {
						final Ref ref = e.getValue();
						printHead(reader, e.getKey(),
								current.equals(ref.getName()), ref);
					}
				}
			}
		}
	}

	private void addRefs(Collection<Ref> refs, String prefix) {
		for (Ref ref : RefComparator.sort(refs)) {
			final String name = ref.getName();
			if (name.startsWith(prefix))
				addRef(name.substring(name.indexOf('/', 5) + 1), ref);
		}
	}

	private void addRef(String name, Ref ref) {
		printRefs.put(name, ref);
		maxNameLength = Math.max(maxNameLength, name.length());
	}

	private void printHead(final ObjectReader reader, final String ref,
			final boolean isCurrent, final Ref refObj) throws IOException {
		outw.print(isCurrent ? '*' : ' ');
		outw.print(' ');
		outw.print(ref);
		if (verbose) {
			final int spaces = maxNameLength - ref.length() + 1;
			outw.format("%" + spaces + "s", ""); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
			final ObjectId objectId = refObj.getObjectId();
			outw.print(reader.abbreviate(objectId).name());
			outw.print(' ');
			outw.print(rw.parseCommit(objectId).getShortMessage());
		}
		outw.println();
	}

	private void delete(List<String> branches, boolean force)
			throws IOException {
		String current = db.getBranch();
		ObjectId head = db.resolve(Constants.HEAD);
		for (String b : branches) {
			if (b.equals(current)) {
				throw die(MessageFormat.format(CLIText.get().cannotDeleteTheBranchWhichYouAreCurrentlyOn, b));
			}
			RefUpdate update = db.updateRef((remote ? Constants.R_REMOTES
					: Constants.R_HEADS)
					+ b);
			update.setNewObjectId(head);
			update.setForceUpdate(force || remote);
			Result result = update.delete();
			if (result == Result.REJECTED) {
				throw die(MessageFormat.format(CLIText.get().branchIsNotAnAncestorOfYourCurrentHEAD, b));
			} else if (result == Result.NEW)
				throw die(MessageFormat.format(CLIText.get().branchNotFound, b));
			if (remote)
				outw.println(MessageFormat.format(CLIText.get().deletedRemoteBranch, b));
			else if (verbose)
				outw.println(MessageFormat.format(CLIText.get().deletedBranch, b));
		}
	}
}
