/*
 * 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 static java.util.stream.Collectors.toCollection;

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.lib.RefUpdate.Result;
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()) {
			// What part of the name space is already taken
			Collection<String> takenNames = refdb.getRefs().stream()
					.map(Ref::getName)
					.collect(toCollection(HashSet::new));
			Collection<String> takenPrefixes = getTakenPrefixes(takenNames);

			// Now to the update that may require more room in the name space
			for (ReceiveCommand cmd : commands2) {
				try {
					if (cmd.getResult() == NOT_ATTEMPTED) {
						cmd.updateType(walk);
						RefUpdate ru = newUpdate(cmd);
						SWITCH: switch (cmd.getType()) {
						case DELETE:
							// Performed in the first phase
							break;
						case UPDATE:
						case UPDATE_NONFASTFORWARD:
							RefUpdate ruu = newUpdate(cmd);
							cmd.setResult(ruu.update(walk));
							break;
						case CREATE:
							for (String prefix : getPrefixes(cmd.getRefName())) {
								if (takenNames.contains(prefix)) {
									cmd.setResult(Result.LOCK_FAILURE);
									break SWITCH;
								}
							}
							if (takenPrefixes.contains(cmd.getRefName())) {
								cmd.setResult(Result.LOCK_FAILURE);
								break SWITCH;
							}
							ru.setCheckConflicting(false);
							takenPrefixes.addAll(getPrefixes(cmd.getRefName()));
							takenNames.add(cmd.getRefName());
							cmd.setResult(ru.update(walk));
						}
					}
				} catch (IOException err) {
					cmd.setResult(REJECTED_OTHER_REASON, MessageFormat.format(
							JGitText.get().lockError, err.getMessage()));
				} finally {
					monitor.update(1);
				}
			}
		}
		monitor.endTask();
	}

	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);
	}

	private static Collection<String> getTakenPrefixes(Collection<String> names) {
		Collection<String> ref = new HashSet<>();
		for (String name : names) {
			addPrefixesTo(name, ref);
		}
		return ref;
	}

	/**
	 * 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();
	}

	/** {@inheritDoc} */
	@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();
	}
}
