/*
 * Copyright (C) 2008-2012, Google Inc.
 * Copyright (C) 2008, 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.lib;

import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED;
import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_OTHER_REASON;

import java.io.IOException;
import java.text.MessageFormat;
import java.time.Duration;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.TimeoutException;

import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.PushCertificate;
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.util.time.ProposedTimestamp;

/**
 * Batch of reference updates to be applied to a repository.
 * <p>
 * The batch update is primarily useful in the transport code, where a client or
 * server is making changes to more than one reference at a time.
 */
public class BatchRefUpdate {
	/**
	 * Maximum delay the calling thread will tolerate while waiting for a
	 * {@code MonotonicClock} to resolve associated {@link ProposedTimestamp}s.
	 * <p>
	 * A default of 5 seconds was chosen by guessing. A common assumption is
	 * clock skew between machines on the same LAN using an NTP server also on
	 * the same LAN should be under 5 seconds. 5 seconds is also not that long
	 * for a large `git push` operation to complete.
	 *
	 * @since 4.9
	 */
	protected static final Duration MAX_WAIT = Duration.ofSeconds(5);

	private final RefDatabase refdb;

	/** Commands to apply during this batch. */
	private final List<ReceiveCommand> commands;

	/** Does the caller permit a forced update on a reference? */
	private boolean allowNonFastForwards;

	/** Identity to record action as within the reflog. */
	private PersonIdent refLogIdent;

	/** Message the caller wants included in the reflog. */
	private String refLogMessage;

	/** Should the result value be appended to {@link #refLogMessage}. */
	private boolean refLogIncludeResult;

	/**
	 * Should reflogs be written even if the configured default for this ref is
	 * not to write it.
	 */
	private boolean forceRefLog;

	/** Push certificate associated with this update. */
	private PushCertificate pushCert;

	/** Whether updates should be atomic. */
	private boolean atomic;

	/** Push options associated with this update. */
	private List<String> pushOptions;

	/** Associated timestamps that should be blocked on before update. */
	private List<ProposedTimestamp> timestamps;

	/**
	 * Initialize a new batch update.
	 *
	 * @param refdb
	 *            the reference database of the repository to be updated.
	 */
	protected BatchRefUpdate(RefDatabase refdb) {
		this.refdb = refdb;
		this.commands = new ArrayList<>();
		this.atomic = refdb.performsAtomicTransactions();
	}

	/**
	 * Whether the batch update will permit a non-fast-forward update to an
	 * existing reference.
	 *
	 * @return true if the batch update will permit a non-fast-forward update to
	 *         an existing reference.
	 */
	public boolean isAllowNonFastForwards() {
		return allowNonFastForwards;
	}

	/**
	 * Set if this update wants to permit a forced update.
	 *
	 * @param allow
	 *            true if this update batch should ignore merge tests.
	 * @return {@code this}.
	 */
	public BatchRefUpdate setAllowNonFastForwards(boolean allow) {
		allowNonFastForwards = allow;
		return this;
	}

	/**
	 * Get identity of the user making the change in the reflog.
	 *
	 * @return identity of the user making the change in the reflog.
	 */
	public PersonIdent getRefLogIdent() {
		return refLogIdent;
	}

	/**
	 * Set the identity of the user appearing in the reflog.
	 * <p>
	 * The timestamp portion of the identity is ignored. A new identity with the
	 * current timestamp will be created automatically when the update occurs
	 * and the log record is written.
	 *
	 * @param pi
	 *            identity of the user. If null the identity will be
	 *            automatically determined based on the repository
	 *            configuration.
	 * @return {@code this}.
	 */
	public BatchRefUpdate setRefLogIdent(PersonIdent pi) {
		refLogIdent = pi;
		return this;
	}

	/**
	 * Get the message to include in the reflog.
	 *
	 * @return message the caller wants to include in the reflog; null if the
	 *         update should not be logged.
	 */
	@Nullable
	public String getRefLogMessage() {
		return refLogMessage;
	}

	/**
	 * Check whether the reflog message should include the result of the update,
	 * such as fast-forward or force-update.
	 * <p>
	 * Describes the default for commands in this batch that do not override it
	 * with
	 * {@link org.eclipse.jgit.transport.ReceiveCommand#setRefLogMessage(String, boolean)}.
	 *
	 * @return true if the message should include the result.
	 */
	public boolean isRefLogIncludingResult() {
		return refLogIncludeResult;
	}

	/**
	 * Set the message to include in the reflog.
	 * <p>
	 * Repository implementations may limit which reflogs are written by
	 * default, based on the project configuration. If a repo is not configured
	 * to write logs for this ref by default, setting the message alone may have
	 * no effect. To indicate that the repo should write logs for this update in
	 * spite of configured defaults, use {@link #setForceRefLog(boolean)}.
	 * <p>
	 * Describes the default for commands in this batch that do not override it
	 * with
	 * {@link org.eclipse.jgit.transport.ReceiveCommand#setRefLogMessage(String, boolean)}.
	 *
	 * @param msg
	 *            the message to describe this change. If null and appendStatus
	 *            is false, the reflog will not be updated.
	 * @param appendStatus
	 *            true if the status of the ref change (fast-forward or
	 *            forced-update) should be appended to the user supplied
	 *            message.
	 * @return {@code this}.
	 */
	public BatchRefUpdate setRefLogMessage(String msg, boolean appendStatus) {
		if (msg == null && !appendStatus)
			disableRefLog();
		else if (msg == null && appendStatus) {
			refLogMessage = ""; //$NON-NLS-1$
			refLogIncludeResult = true;
		} else {
			refLogMessage = msg;
			refLogIncludeResult = appendStatus;
		}
		return this;
	}

	/**
	 * Don't record this update in the ref's associated reflog.
	 * <p>
	 * Equivalent to {@code setRefLogMessage(null, false)}.
	 *
	 * @return {@code this}.
	 */
	public BatchRefUpdate disableRefLog() {
		refLogMessage = null;
		refLogIncludeResult = false;
		return this;
	}

	/**
	 * Force writing a reflog for the updated ref.
	 *
	 * @param force whether to force.
	 * @return {@code this}
	 * @since 4.9
	 */
	public BatchRefUpdate setForceRefLog(boolean force) {
		forceRefLog = force;
		return this;
	}

	/**
	 * Check whether log has been disabled by {@link #disableRefLog()}.
	 *
	 * @return true if disabled.
	 */
	public boolean isRefLogDisabled() {
		return refLogMessage == null;
	}

	/**
	 * Check whether the reflog should be written regardless of repo defaults.
	 *
	 * @return whether force writing is enabled.
	 * @since 4.9
	 */
	protected boolean isForceRefLog() {
		return forceRefLog;
	}

	/**
	 * Request that all updates in this batch be performed atomically.
	 * <p>
	 * When atomic updates are used, either all commands apply successfully, or
	 * none do. Commands that might have otherwise succeeded are rejected with
	 * {@code REJECTED_OTHER_REASON}.
	 * <p>
	 * This method only works if the underlying ref database supports atomic
	 * transactions, i.e.
	 * {@link org.eclipse.jgit.lib.RefDatabase#performsAtomicTransactions()}
	 * returns true. Calling this method with true if the underlying ref
	 * database does not support atomic transactions will cause all commands to
	 * fail with {@code
	 * REJECTED_OTHER_REASON}.
	 *
	 * @param atomic
	 *            whether updates should be atomic.
	 * @return {@code this}
	 * @since 4.4
	 */
	public BatchRefUpdate setAtomic(boolean atomic) {
		this.atomic = atomic;
		return this;
	}

	/**
	 * Whether updates should be atomic.
	 *
	 * @return atomic whether updates should be atomic.
	 * @since 4.4
	 */
	public boolean isAtomic() {
		return atomic;
	}

	/**
	 * Set a push certificate associated with this update.
	 * <p>
	 * This usually includes commands to update the refs in this batch, but is not
	 * required to.
	 *
	 * @param cert
	 *            push certificate, may be null.
	 * @since 4.1
	 */
	public void setPushCertificate(PushCertificate cert) {
		pushCert = cert;
	}

	/**
	 * Set the push certificate associated with this update.
	 * <p>
	 * This usually includes commands to update the refs in this batch, but is not
	 * required to.
	 *
	 * @return push certificate, may be null.
	 * @since 4.1
	 */
	protected PushCertificate getPushCertificate() {
		return pushCert;
	}

	/**
	 * Get commands this update will process.
	 *
	 * @return commands this update will process.
	 */
	public List<ReceiveCommand> getCommands() {
		return Collections.unmodifiableList(commands);
	}

	/**
	 * Add a single command to this batch update.
	 *
	 * @param cmd
	 *            the command to add, must not be null.
	 * @return {@code this}.
	 */
	public BatchRefUpdate addCommand(ReceiveCommand cmd) {
		commands.add(cmd);
		return this;
	}

	/**
	 * Add commands to this batch update.
	 *
	 * @param cmd
	 *            the commands to add, must not be null.
	 * @return {@code this}.
	 */
	public BatchRefUpdate addCommand(ReceiveCommand... cmd) {
		return addCommand(Arrays.asList(cmd));
	}

	/**
	 * Add commands to this batch update.
	 *
	 * @param cmd
	 *            the commands to add, must not be null.
	 * @return {@code this}.
	 */
	public BatchRefUpdate addCommand(Collection<ReceiveCommand> cmd) {
		commands.addAll(cmd);
		return this;
	}

	/**
	 * Gets the list of option strings associated with this update.
	 *
	 * @return push options that were passed to {@link #execute}; prior to calling
	 *         {@link #execute}, always returns null.
	 * @since 4.5
	 */
	@Nullable
	public List<String> getPushOptions() {
		return pushOptions;
	}

	/**
	 * Set push options associated with this update.
	 * <p>
	 * Implementations must call this at the top of {@link #execute(RevWalk,
	 * ProgressMonitor, List)}.
	 *
	 * @param options options passed to {@code execute}.
	 * @since 4.9
	 */
	protected void setPushOptions(List<String> options) {
		pushOptions = options;
	}

	/**
	 * Get list of timestamps the batch must wait for.
	 *
	 * @return list of timestamps the batch must wait for.
	 * @since 4.6
	 */
	public List<ProposedTimestamp> getProposedTimestamps() {
		if (timestamps != null) {
			return Collections.unmodifiableList(timestamps);
		}
		return Collections.emptyList();
	}

	/**
	 * Request the batch to wait for the affected timestamps to resolve.
	 *
	 * @param ts
	 *            a {@link org.eclipse.jgit.util.time.ProposedTimestamp} object.
	 * @return {@code this}.
	 * @since 4.6
	 */
	public BatchRefUpdate addProposedTimestamp(ProposedTimestamp ts) {
		if (timestamps == null) {
			timestamps = new ArrayList<>(4);
		}
		timestamps.add(ts);
		return this;
	}

	/**
	 * Execute this batch update.
	 * <p>
	 * The default implementation of this method performs a sequential reference
	 * update over each reference.
	 * <p>
	 * Implementations must respect the atomicity requirements of the underlying
	 * database as described in {@link #setAtomic(boolean)} and
	 * {@link org.eclipse.jgit.lib.RefDatabase#performsAtomicTransactions()}.
	 *
	 * @param walk
	 *            a RevWalk to parse tags in case the storage system wants to
	 *            store them pre-peeled, a common performance optimization.
	 * @param monitor
	 *            progress monitor to receive update status on.
	 * @param options
	 *            a list of option strings; set null to execute without
	 * @throws java.io.IOException
	 *             the database is unable to accept the update. Individual
	 *             command status must be tested to determine if there is a
	 *             partial failure, or a total failure.
	 * @since 4.5
	 */
	public void execute(RevWalk walk, ProgressMonitor monitor,
			List<String> options) throws IOException {

		if (atomic && !refdb.performsAtomicTransactions()) {
			for (ReceiveCommand c : commands) {
				if (c.getResult() == NOT_ATTEMPTED) {
					c.setResult(REJECTED_OTHER_REASON,
							JGitText.get().atomicRefUpdatesNotSupported);
				}
			}
			return;
		}
		if (!blockUntilTimestamps(MAX_WAIT)) {
			return;
		}

		if (options != null) {
			setPushOptions(options);
		}

		monitor.beginTask(JGitText.get().updatingReferences, commands.size());
		List<ReceiveCommand> commands2 = new ArrayList<>(
				commands.size());
		// First delete refs. This may free the name space for some of the
		// updates.
		for (ReceiveCommand cmd : commands) {
			try {
				if (cmd.getResult() == NOT_ATTEMPTED) {
					if (isMissing(walk, cmd.getOldId())
							|| isMissing(walk, cmd.getNewId())) {
						cmd.setResult(ReceiveCommand.Result.REJECTED_MISSING_OBJECT);
						continue;
					}
					cmd.updateType(walk);
					switch (cmd.getType()) {
					case CREATE:
						commands2.add(cmd);
						break;
					case UPDATE:
					case UPDATE_NONFASTFORWARD:
						commands2.add(cmd);
						break;
					case DELETE:
						RefUpdate rud = newUpdate(cmd);
						monitor.update(1);
						cmd.setResult(rud.delete(walk));
					}
				}
			} catch (IOException err) {
				cmd.setResult(
						REJECTED_OTHER_REASON,
						MessageFormat.format(JGitText.get().lockError,
								err.getMessage()));
			}
		}
		if (!commands2.isEmpty()) {
			// Perform updates that may require more room in the name space
			for (ReceiveCommand cmd : commands2) {
				try {
					if (cmd.getResult() == NOT_ATTEMPTED) {
						cmd.updateType(walk);
						switch (cmd.getType()) {
							case DELETE:
								// Performed in the first phase
								break;
							case UPDATE:
							case UPDATE_NONFASTFORWARD:
							case CREATE:
								RefUpdate ru = newUpdate(cmd);
								cmd.setResult(ru.update(walk));
								break;
						}
					}
				} catch (IOException err) {
					cmd.setResult(REJECTED_OTHER_REASON, MessageFormat.format(
							JGitText.get().lockError, err.getMessage()));
				} finally {
					monitor.update(1);
				}
			}
		}
		monitor.endTask();
	}

	/**
	 * Get the ref database associated with this update.
	 *
	 * @return the ref database.
	 * @since 6.6
	 */
	protected RefDatabase getRefDatabase() {
		return refdb;
	}

	private static boolean isMissing(RevWalk walk, ObjectId id)
			throws IOException {
		if (id.equals(ObjectId.zeroId())) {
			return false; // Explicit add or delete is not missing.
		}
		try {
			walk.parseAny(id);
			return false;
		} catch (MissingObjectException e) {
			return true;
		}
	}

	/**
	 * Wait for timestamps to be in the past, aborting commands on timeout.
	 *
	 * @param maxWait
	 *            maximum amount of time to wait for timestamps to resolve.
	 * @return true if timestamps were successfully waited for; false if
	 *         commands were aborted.
	 * @since 4.6
	 */
	protected boolean blockUntilTimestamps(Duration maxWait) {
		if (timestamps == null) {
			return true;
		}
		try {
			ProposedTimestamp.blockUntil(timestamps, maxWait);
			return true;
		} catch (TimeoutException | InterruptedException e) {
			String msg = JGitText.get().timeIsUncertain;
			for (ReceiveCommand c : commands) {
				if (c.getResult() == NOT_ATTEMPTED) {
					c.setResult(REJECTED_OTHER_REASON, msg);
				}
			}
			return false;
		}
	}

	/**
	 * Execute this batch update without option strings.
	 *
	 * @param walk
	 *            a RevWalk to parse tags in case the storage system wants to
	 *            store them pre-peeled, a common performance optimization.
	 * @param monitor
	 *            progress monitor to receive update status on.
	 * @throws java.io.IOException
	 *             the database is unable to accept the update. Individual
	 *             command status must be tested to determine if there is a
	 *             partial failure, or a total failure.
	 */
	public void execute(RevWalk walk, ProgressMonitor monitor)
			throws IOException {
		execute(walk, monitor, null);
	}

	/**
	 * Get all path prefixes of a ref name.
	 *
	 * @param name
	 *            ref name.
	 * @return path prefixes of the ref name. For {@code refs/heads/foo}, returns
	 *         {@code refs} and {@code refs/heads}.
	 * @since 4.9
	 */
	protected static Collection<String> getPrefixes(String name) {
		Collection<String> ret = new HashSet<>();
		addPrefixesTo(name, ret);
		return ret;
	}

	/**
	 * Add prefixes of a ref name to an existing collection.
	 *
	 * @param name
	 *            ref name.
	 * @param out
	 *            path prefixes of the ref name. For {@code refs/heads/foo},
	 *            returns {@code refs} and {@code refs/heads}.
	 * @since 4.9
	 */
	protected static void addPrefixesTo(String name, Collection<String> out) {
		int p1 = name.indexOf('/');
		while (p1 > 0) {
			out.add(name.substring(0, p1));
			p1 = name.indexOf('/', p1 + 1);
		}
	}

	/**
	 * Create a new RefUpdate copying the batch settings.
	 *
	 * @param cmd
	 *            specific command the update should be created to copy.
	 * @return a single reference update command.
	 * @throws java.io.IOException
	 *             the reference database cannot make a new update object for
	 *             the given reference.
	 */
	protected RefUpdate newUpdate(ReceiveCommand cmd) throws IOException {
		RefUpdate ru = refdb.newUpdate(cmd.getRefName(), false);
		if (isRefLogDisabled(cmd)) {
			ru.disableRefLog();
		} else {
			ru.setRefLogIdent(refLogIdent);
			ru.setRefLogMessage(getRefLogMessage(cmd), isRefLogIncludingResult(cmd));
			ru.setForceRefLog(isForceRefLog(cmd));
		}
		ru.setPushCertificate(pushCert);
		switch (cmd.getType()) {
		case DELETE:
			if (!ObjectId.zeroId().equals(cmd.getOldId()))
				ru.setExpectedOldObjectId(cmd.getOldId());
			ru.setForceUpdate(true);
			return ru;

		case CREATE:
		case UPDATE:
		case UPDATE_NONFASTFORWARD:
		default:
			ru.setForceUpdate(isAllowNonFastForwards());
			ru.setExpectedOldObjectId(cmd.getOldId());
			ru.setNewObjectId(cmd.getNewId());
			return ru;
		}
	}

	/**
	 * Check whether reflog is disabled for a command.
	 *
	 * @param cmd
	 *            specific command.
	 * @return whether the reflog is disabled, taking into account the state from
	 *         this instance as well as overrides in the given command.
	 * @since 4.9
	 */
	protected boolean isRefLogDisabled(ReceiveCommand cmd) {
		return cmd.hasCustomRefLog() ? cmd.isRefLogDisabled() : isRefLogDisabled();
	}

	/**
	 * Get reflog message for a command.
	 *
	 * @param cmd
	 *            specific command.
	 * @return reflog message, taking into account the state from this instance as
	 *         well as overrides in the given command.
	 * @since 4.9
	 */
	protected String getRefLogMessage(ReceiveCommand cmd) {
		return cmd.hasCustomRefLog() ? cmd.getRefLogMessage() : getRefLogMessage();
	}

	/**
	 * Check whether the reflog message for a command should include the result.
	 *
	 * @param cmd
	 *            specific command.
	 * @return whether the reflog message should show the result, taking into
	 *         account the state from this instance as well as overrides in the
	 *         given command.
	 * @since 4.9
	 */
	protected boolean isRefLogIncludingResult(ReceiveCommand cmd) {
		return cmd.hasCustomRefLog()
				? cmd.isRefLogIncludingResult() : isRefLogIncludingResult();
	}

	/**
	 * Check whether the reflog for a command should be written regardless of repo
	 * defaults.
	 *
	 * @param cmd
	 *            specific command.
	 * @return whether force writing is enabled.
	 * @since 4.9
	 */
	protected boolean isForceRefLog(ReceiveCommand cmd) {
		Boolean isForceRefLog = cmd.isForceRefLog();
		return isForceRefLog != null ? isForceRefLog.booleanValue()
				: isForceRefLog();
	}

	@Override
	public String toString() {
		StringBuilder r = new StringBuilder();
		r.append(getClass().getSimpleName()).append('[');
		if (commands.isEmpty())
			return r.append(']').toString();

		r.append('\n');
		for (ReceiveCommand cmd : commands) {
			r.append("  "); //$NON-NLS-1$
			r.append(cmd);
			r.append("  (").append(cmd.getResult()); //$NON-NLS-1$
			if (cmd.getMessage() != null) {
				r.append(": ").append(cmd.getMessage()); //$NON-NLS-1$
			}
			r.append(")\n"); //$NON-NLS-1$
		}
		return r.append(']').toString();
	}
}
