/*
 * Copyright (C) 2010, 2020 Chris Aniszczyk <caniszczyk@gmail.com> 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.api;

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

import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.InvalidTagNameException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.api.errors.NoHeadException;
import org.eclipse.jgit.api.errors.RefAlreadyExistsException;
import org.eclipse.jgit.api.errors.ServiceUnavailableException;
import org.eclipse.jgit.api.errors.UnsupportedSigningFormatException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.GpgConfig;
import org.eclipse.jgit.lib.GpgConfig.GpgFormat;
import org.eclipse.jgit.lib.GpgObjectSigner;
import org.eclipse.jgit.lib.GpgSigner;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.TagBuilder;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.CredentialsProvider;

/**
 * Create/update an annotated tag object or a simple unannotated tag
 * <p>
 * Examples (<code>git</code> is a {@link org.eclipse.jgit.api.Git} instance):
 * <p>
 * Create a new tag for the current commit:
 *
 * <pre>
 * git.tag().setName(&quot;v1.0&quot;).setMessage(&quot;First stable release&quot;).call();
 * </pre>
 * <p>
 *
 * Create a new unannotated tag for the current commit:
 *
 * <pre>
 * git.tag().setName(&quot;v1.0&quot;).setAnnotated(false).call();
 * </pre>
 *
 * @see <a href="http://www.kernel.org/pub/software/scm/git/docs/git-tag.html"
 *      >Git documentation about Tag</a>
 */
public class TagCommand extends GitCommand<Ref> {

	private RevObject id;

	private String name;

	private String message;

	private PersonIdent tagger;

	private Boolean signed;

	private boolean forceUpdate;

	private Boolean annotated;

	private String signingKey;

	private GpgConfig gpgConfig;

	private GpgObjectSigner gpgSigner;

	private CredentialsProvider credentialsProvider;

	/**
	 * <p>Constructor for TagCommand.</p>
	 *
	 * @param repo a {@link org.eclipse.jgit.lib.Repository} object.
	 */
	protected TagCommand(Repository repo) {
		super(repo);
		this.credentialsProvider = CredentialsProvider.getDefault();
	}

	/**
	 * {@inheritDoc}
	 * <p>
	 * Executes the {@code tag} command with all the options and parameters
	 * collected by the setter methods of this class. Each instance of this
	 * class should only be used for one invocation of the command (means: one
	 * call to {@link #call()})
	 *
	 * @since 2.0
	 */
	@Override
	public Ref call() throws GitAPIException, ConcurrentRefUpdateException,
			InvalidTagNameException, NoHeadException {
		checkCallable();
		processOptions();

		try (RevWalk revWalk = new RevWalk(repo)) {
			// if no id is set, we should attempt to use HEAD
			if (id == null) {
				ObjectId objectId = repo.resolve(Constants.HEAD + "^{commit}"); //$NON-NLS-1$
				if (objectId == null)
					throw new NoHeadException(
							JGitText.get().tagOnRepoWithoutHEADCurrentlyNotSupported);

				id = revWalk.parseCommit(objectId);
			}

			if (!isAnnotated()) {
				return updateTagRef(id, revWalk, name,
						"SimpleTag[" + name + " : " + id //$NON-NLS-1$ //$NON-NLS-2$
								+ "]"); //$NON-NLS-1$
			}

			// create the tag object
			TagBuilder newTag = new TagBuilder();
			newTag.setTag(name);
			newTag.setMessage(message);
			newTag.setTagger(tagger);
			newTag.setObjectId(id);

			if (gpgSigner != null) {
				gpgSigner.signObject(newTag, signingKey, tagger,
						credentialsProvider, gpgConfig);
			}

			// write the tag object
			try (ObjectInserter inserter = repo.newObjectInserter()) {
				ObjectId tagId = inserter.insert(newTag);
				inserter.flush();

				String tag = newTag.getTag();
				return updateTagRef(tagId, revWalk, tag, newTag.toString());

			}

		} catch (IOException e) {
			throw new JGitInternalException(
					JGitText.get().exceptionCaughtDuringExecutionOfTagCommand,
					e);
		}
	}

	private Ref updateTagRef(ObjectId tagId, RevWalk revWalk,
			String tagName, String newTagToString) throws IOException,
			ConcurrentRefUpdateException, RefAlreadyExistsException {
		String refName = Constants.R_TAGS + tagName;
		RefUpdate tagRef = repo.updateRef(refName);
		tagRef.setNewObjectId(tagId);
		tagRef.setForceUpdate(forceUpdate);
		tagRef.setRefLogMessage("tagged " + name, false); //$NON-NLS-1$
		Result updateResult = tagRef.update(revWalk);
		switch (updateResult) {
		case NEW:
		case FORCED:
			return repo.exactRef(refName);
		case LOCK_FAILURE:
			throw new ConcurrentRefUpdateException(
					JGitText.get().couldNotLockHEAD, tagRef.getRef(),
					updateResult);
		case NO_CHANGE:
			if (forceUpdate) {
				return repo.exactRef(refName);
			}
			throw new RefAlreadyExistsException(MessageFormat
					.format(JGitText.get().tagAlreadyExists, newTagToString),
					updateResult);
		case REJECTED:
			throw new RefAlreadyExistsException(MessageFormat.format(
					JGitText.get().tagAlreadyExists, newTagToString),
					updateResult);
		default:
			throw new JGitInternalException(MessageFormat.format(
					JGitText.get().updatingRefFailed, refName, newTagToString,
					updateResult));
		}
	}

	/**
	 * Sets default values for not explicitly specified options. Then validates
	 * that all required data has been provided.
	 *
	 * @throws InvalidTagNameException
	 *             if the tag name is null or invalid
	 * @throws ServiceUnavailableException
	 *             if the tag should be signed but no signer can be found
	 * @throws UnsupportedSigningFormatException
	 *             if the tag should be signed but {@code gpg.format} is not
	 *             {@link GpgFormat#OPENPGP}
	 */
	private void processOptions()
			throws InvalidTagNameException, ServiceUnavailableException,
			UnsupportedSigningFormatException {
		if (name == null
				|| !Repository.isValidRefName(Constants.R_TAGS + name)) {
			throw new InvalidTagNameException(
					MessageFormat.format(JGitText.get().tagNameInvalid,
							name == null ? "<null>" : name)); //$NON-NLS-1$
		}
		if (!isAnnotated()) {
			if ((message != null && !message.isEmpty()) || tagger != null) {
				throw new JGitInternalException(JGitText
						.get().messageAndTaggerNotAllowedInUnannotatedTags);
			}
		} else {
			if (tagger == null) {
				tagger = new PersonIdent(repo);
			}
			// Figure out whether to sign.
			if (!(Boolean.FALSE.equals(signed) && signingKey == null)) {
				if (gpgConfig == null) {
					gpgConfig = new GpgConfig(repo.getConfig());
				}
				boolean doSign = isSigned() || gpgConfig.isSignAllTags();
				if (!Boolean.TRUE.equals(annotated) && !doSign) {
					doSign = gpgConfig.isSignAnnotated();
				}
				if (doSign) {
					if (signingKey == null) {
						signingKey = gpgConfig.getSigningKey();
					}
					if (gpgSigner == null) {
						GpgSigner signer = GpgSigner.getDefault();
						if (!(signer instanceof GpgObjectSigner)) {
							throw new ServiceUnavailableException(
									JGitText.get().signingServiceUnavailable);
						}
						gpgSigner = (GpgObjectSigner) signer;
					}
					// The message of a signed tag must end in a newline because
					// the signature will be appended.
					if (message != null && !message.isEmpty()
							&& !message.endsWith("\n")) { //$NON-NLS-1$
						message += '\n';
					}
				}
			}
		}
	}

	/**
	 * Set the tag <code>name</code>.
	 *
	 * @param name
	 *            the tag name used for the {@code tag}
	 * @return {@code this}
	 */
	public TagCommand setName(String name) {
		checkCallable();
		this.name = name;
		return this;
	}

	/**
	 * Get the tag <code>name</code>.
	 *
	 * @return the tag name used for the <code>tag</code>
	 */
	public String getName() {
		return name;
	}

	/**
	 * Get the tag <code>message</code>.
	 *
	 * @return the tag message used for the <code>tag</code>
	 */
	public String getMessage() {
		return message;
	}

	/**
	 * Set the tag <code>message</code>.
	 *
	 * @param message
	 *            the tag message used for the {@code tag}
	 * @return {@code this}
	 */
	public TagCommand setMessage(String message) {
		checkCallable();
		this.message = message;
		return this;
	}

	/**
	 * Whether {@link #setSigned(boolean) setSigned(true)} has been called or
	 * whether a {@link #setSigningKey(String) signing key ID} has been set;
	 * i.e., whether -s or -u was specified explicitly.
	 *
	 * @return whether the tag is signed
	 */
	public boolean isSigned() {
		return Boolean.TRUE.equals(signed) || signingKey != null;
	}

	/**
	 * If set to true the Tag command creates a signed tag object. This
	 * corresponds to the parameter -s (--sign or --no-sign) on the command
	 * line.
	 * <p>
	 * If {@code true}, the tag will be a signed annotated tag.
	 * </p>
	 *
	 * @param signed
	 *            whether to sign
	 * @return {@code this}
	 */
	public TagCommand setSigned(boolean signed) {
		checkCallable();
		this.signed = Boolean.valueOf(signed);
		return this;
	}

	/**
	 * Sets the {@link GpgSigner} to use if the commit is to be signed.
	 *
	 * @param signer
	 *            to use; if {@code null}, the default signer will be used
	 * @return {@code this}
	 * @since 5.11
	 */
	public TagCommand setGpgSigner(GpgObjectSigner signer) {
		checkCallable();
		this.gpgSigner = signer;
		return this;
	}

	/**
	 * Sets an external {@link GpgConfig} to use. Whether it will be used is at
	 * the discretion of the {@link #setGpgSigner(GpgObjectSigner)}.
	 *
	 * @param config
	 *            to set; if {@code null}, the config will be loaded from the
	 *            git config of the repository
	 * @return {@code this}
	 * @since 5.11
	 */
	public TagCommand setGpgConfig(GpgConfig config) {
		checkCallable();
		this.gpgConfig = config;
		return this;
	}

	/**
	 * Sets the tagger of the tag. If the tagger is null, a PersonIdent will be
	 * created from the info in the repository.
	 *
	 * @param tagger
	 *            a {@link org.eclipse.jgit.lib.PersonIdent} object.
	 * @return {@code this}
	 */
	public TagCommand setTagger(PersonIdent tagger) {
		checkCallable();
		this.tagger = tagger;
		return this;
	}

	/**
	 * Get the <code>tagger</code> who created the tag.
	 *
	 * @return the tagger of the tag
	 */
	public PersonIdent getTagger() {
		return tagger;
	}

	/**
	 * Get the tag's object id
	 *
	 * @return the object id of the tag
	 */
	public RevObject getObjectId() {
		return id;
	}

	/**
	 * Sets the object id of the tag. If the object id is {@code null}, the
	 * commit pointed to from HEAD will be used.
	 *
	 * @param id
	 *            a {@link org.eclipse.jgit.revwalk.RevObject} object.
	 * @return {@code this}
	 */
	public TagCommand setObjectId(RevObject id) {
		checkCallable();
		this.id = id;
		return this;
	}

	/**
	 * Whether this is a forced update
	 *
	 * @return is this a force update
	 */
	public boolean isForceUpdate() {
		return forceUpdate;
	}

	/**
	 * If set to true the Tag command may replace an existing tag object. This
	 * corresponds to the parameter -f on the command line.
	 *
	 * @param forceUpdate
	 *            whether this is a forced update
	 * @return {@code this}
	 */
	public TagCommand setForceUpdate(boolean forceUpdate) {
		checkCallable();
		this.forceUpdate = forceUpdate;
		return this;
	}

	/**
	 * Configure this tag to be created as an annotated tag
	 *
	 * @param annotated
	 *            whether this shall be an annotated tag
	 * @return {@code this}
	 * @since 3.0
	 */
	public TagCommand setAnnotated(boolean annotated) {
		checkCallable();
		this.annotated = Boolean.valueOf(annotated);
		return this;
	}

	/**
	 * Whether this will create an annotated tag.
	 *
	 * @return true if this command will create an annotated tag (default is
	 *         true)
	 * @since 3.0
	 */
	public boolean isAnnotated() {
		boolean setExplicitly = Boolean.TRUE.equals(annotated) || isSigned();
		if (setExplicitly) {
			return true;
		}
		// Annotated at default (not set explicitly)
		return annotated == null;
	}

	/**
	 * Sets the signing key.
	 * <p>
	 * Per spec of {@code user.signingKey}: this will be sent to the GPG program
	 * as is, i.e. can be anything supported by the GPG program.
	 * </p>
	 * <p>
	 * Note, if none was set or {@code null} is specified a default will be
	 * obtained from the configuration.
	 * </p>
	 * <p>
	 * If set to a non-{@code null} value, the tag will be a signed annotated
	 * tag.
	 * </p>
	 *
	 * @param signingKey
	 *            signing key; {@code null} allowed
	 * @return {@code this}
	 * @since 5.11
	 */
	public TagCommand setSigningKey(String signingKey) {
		checkCallable();
		this.signingKey = signingKey;
		return this;
	}

	/**
	 * Retrieves the signing key ID.
	 *
	 * @return the key ID set, or {@code null} if none is set
	 * @since 5.11
	 */
	public String getSigningKey() {
		return signingKey;
	}

	/**
	 * Sets a {@link CredentialsProvider}
	 *
	 * @param credentialsProvider
	 *            the provider to use when querying for credentials (eg., during
	 *            signing)
	 * @return {@code this}
	 * @since 5.11
	 */
	public TagCommand setCredentialsProvider(
			CredentialsProvider credentialsProvider) {
		checkCallable();
		this.credentialsProvider = credentialsProvider;
		return this;
	}

}
