/*
 * Copyright (C) 2010, Chris Aniszczyk <caniszczyk@gmail.com>
 * Copyright (C) 2009, Google Inc.
 * Copyright (C) 2008, Charles O'Farrell <charleso@charleso.org>
 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg.lists@dewire.com>
 * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com>
 * Copyright (C) 2008, 2021 Shawn O. Pearce <spearce@spearce.org> and others
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Distribution License v. 1.0 which is available at
 * https://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: BSD-3-Clause
 */

package org.eclipse.jgit.pgm;

import java.io.IOException;
import java.text.MessageFormat;
import java.util.List;

import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.ListTagCommand;
import org.eclipse.jgit.api.TagCommand;
import org.eclipse.jgit.api.VerificationResult;
import org.eclipse.jgit.api.VerifySignatureCommand;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.GpgSignatureVerifier.SignatureVerification;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.pgm.internal.CLIText;
import org.eclipse.jgit.pgm.internal.VerificationUtils;
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;
import org.kohsuke.args4j.Argument;
import org.kohsuke.args4j.Option;

@Command(common = true, usage = "usage_CreateATag")
class Tag extends TextBuiltin {

	@Option(name = "--force", aliases = { "-f" }, forbids = { "--delete",
			"--verify" }, usage = "usage_forceReplacingAnExistingTag")
	private boolean force;

	@Option(name = "--delete", aliases = { "-d" }, forbids = {
			"--verify" }, usage = "usage_tagDelete")
	private boolean delete;

	@Option(name = "--annotate", aliases = {
			"-a" }, forbids = { "--delete",
					"--verify" }, usage = "usage_tagAnnotated")
	private boolean annotated;

	@Option(name = "-m", forbids = { "--delete",
			"--verify" }, metaVar = "metaVar_message", usage = "usage_tagMessage")
	private String message;

	@Option(name = "--sign", aliases = { "-s" }, forbids = {
			"--no-sign", "--delete", "--verify" }, usage = "usage_tagSign")
	private boolean sign;

	@Option(name = "--no-sign", usage = "usage_tagNoSign", forbids = {
			"--sign", "--delete", "--verify" })
	private boolean noSign;

	@Option(name = "--local-user", aliases = {
			"-u" }, forbids = { "--delete",
					"--verify" }, metaVar = "metaVar_tagLocalUser", usage = "usage_tagLocalUser")
	private String gpgKeyId;

	@Option(name = "--verify", aliases = { "-v" }, forbids = { "--delete",
			"--force", "--annotate", "-m", "--sign", "--no-sign",
			"--local-user" }, usage = "usage_tagVerify")
	private boolean verify;

	@Argument(index = 0, metaVar = "metaVar_name")
	private String tagName;

	@Argument(index = 1, metaVar = "metaVar_object")
	private ObjectId object;

	/** {@inheritDoc} */
	@Override
	protected void run() {
		try (Git git = new Git(db)) {
			if (tagName != null) {
				if (verify) {
					VerifySignatureCommand verifySig = git.verifySignature()
							.setMode(VerifySignatureCommand.VerifyMode.TAGS)
							.addName(tagName);

					VerificationResult verification = verifySig.call()
							.get(tagName);
					if (verification == null) {
						showUnsigned(git, tagName);
					} else {
						Throwable error = verification.getException();
						if (error != null) {
							throw die(error.getMessage(), error);
						}
						writeVerification(verifySig.getVerifier().getName(),
								(RevTag) verification.getObject(),
								verification.getVerification());
					}
				} else if (delete) {
					List<String> deletedTags = git.tagDelete().setTags(tagName)
							.call();
					if (deletedTags.isEmpty()) {
						throw die(MessageFormat
								.format(CLIText.get().tagNotFound, tagName));
					}
				} else {
					TagCommand command = git.tag().setForceUpdate(force)
							.setMessage(message).setName(tagName);

					if (object != null) {
						try (RevWalk walk = new RevWalk(db)) {
							command.setObjectId(walk.parseAny(object));
						}
					}
					if (noSign) {
						command.setSigned(false);
					} else if (sign) {
						command.setSigned(true);
					}
					if (annotated) {
						command.setAnnotated(true);
					} else if (message == null && !sign && gpgKeyId == null) {
						// None of -a, -m, -s, -u given
						command.setAnnotated(false);
					}
					command.setSigningKey(gpgKeyId);
					try {
						command.call();
					} catch (RefAlreadyExistsException e) {
						throw die(MessageFormat.format(
								CLIText.get().tagAlreadyExists, tagName), e);
					}
				}
			} else {
				ListTagCommand command = git.tagList();
				List<Ref> list = command.call();
				for (Ref ref : list) {
					outw.println(Repository.shortenRefName(ref.getName()));
				}
			}
		} catch (GitAPIException | IOException e) {
			throw die(e.getMessage(), e);
		}
	}

	private void showUnsigned(Git git, String wantedTag) throws IOException {
		ObjectId id = git.getRepository().resolve(wantedTag);
		if (id != null && !ObjectId.zeroId().equals(id)) {
			try (RevWalk walk = new RevWalk(git.getRepository())) {
				showTag(walk.parseTag(id));
			}
		} else {
			throw die(
					MessageFormat.format(CLIText.get().tagNotFound, wantedTag));
		}
	}

	private void showTag(RevTag tag) throws IOException {
		outw.println("object " + tag.getObject().name()); //$NON-NLS-1$
		outw.println("type " + Constants.typeString(tag.getObject().getType())); //$NON-NLS-1$
		outw.println("tag " + tag.getTagName()); //$NON-NLS-1$
		outw.println("tagger " + tag.getTaggerIdent().toExternalString()); //$NON-NLS-1$
		outw.println();
		outw.print(tag.getFullMessage());
	}

	private void writeVerification(String name, RevTag tag,
			SignatureVerification verification) throws IOException {
		showTag(tag);
		if (verification == null) {
			outw.println();
			return;
		}
		VerificationUtils.writeVerification(outw, verification, name,
				tag.getTaggerIdent());
	}
}
