/*
 * Copyright (C) 2019, Google Inc. 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.internal.storage.reftable;

import org.eclipse.jgit.annotations.Nullable;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefDatabase;
import org.eclipse.jgit.lib.ReflogEntry;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.SymbolicRef;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevTag;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.concurrent.locks.Lock;
import java.util.stream.Collectors;

import static org.eclipse.jgit.lib.Ref.Storage.NEW;
import static org.eclipse.jgit.lib.Ref.Storage.PACKED;

import static org.eclipse.jgit.transport.ReceiveCommand.Result.LOCK_FAILURE;
import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED;
import static org.eclipse.jgit.transport.ReceiveCommand.Result.OK;
import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_MISSING_OBJECT;
import static org.eclipse.jgit.transport.ReceiveCommand.Result.REJECTED_NONFASTFORWARD;
import static org.eclipse.jgit.transport.ReceiveCommand.Type.DELETE;
import static org.eclipse.jgit.transport.ReceiveCommand.Type.UPDATE_NONFASTFORWARD;

/**
 * {@link org.eclipse.jgit.lib.BatchRefUpdate} for Reftable based RefDatabase.
 */
public abstract class ReftableBatchRefUpdate extends BatchRefUpdate {
	private final Lock lock;

	private final ReftableDatabase refDb;

	private final Repository repository;

	/**
	 * Initialize.
	 *
	 * @param refdb
	 *            The RefDatabase
	 * @param reftableDb
	 *            The ReftableDatabase
	 * @param lock
	 *            A lock protecting the refdatabase's state
	 * @param repository
	 *            The repository on which this update will run
	 */
	protected ReftableBatchRefUpdate(RefDatabase refdb, ReftableDatabase reftableDb, Lock lock,
			Repository repository) {
		super(refdb);
		this.refDb = reftableDb;
		this.lock = lock;
		this.repository = repository;
	}

	/** {@inheritDoc} */
	@Override
	public void execute(RevWalk rw, ProgressMonitor pm, List<String> options) {
		List<ReceiveCommand> pending = getPending();
		if (pending.isEmpty()) {
			return;
		}
		if (options != null) {
			setPushOptions(options);
		}
		try {
			if (!checkObjectExistence(rw, pending)) {
				return;
			}
			// if we are here, checkObjectExistence might have flagged some problems
			// but the transaction is not atomic, so we should proceed with the other
			// pending commands.
			pending = getPending();
			if (!checkNonFastForwards(rw, pending)) {
				return;
			}
			pending = getPending();

			lock.lock();
			try {
				if (!checkExpected(pending)) {
					return;
				}
				pending = getPending();
				if (!checkConflicting(pending)) {
					return;
				}
				pending = getPending();
				if (!blockUntilTimestamps(MAX_WAIT)) {
					return;
				}

				List<Ref> newRefs = toNewRefs(rw, pending);
				applyUpdates(newRefs, pending);
				for (ReceiveCommand cmd : pending) {
					if (cmd.getResult() == NOT_ATTEMPTED) {
						// XXX this is a bug in DFS ?
						cmd.setResult(OK);
					}
				}
			} finally {
				lock.unlock();
			}
		} catch (IOException e) {
			pending.get(0).setResult(LOCK_FAILURE, "io error"); //$NON-NLS-1$
			ReceiveCommand.abort(pending);
		}
	}

	/**
	 * Implements the storage-specific part of the update.
	 *
	 * @param newRefs
	 *            the new refs to create
	 * @param pending
	 *            the pending receive commands to be executed
	 * @throws IOException
	 *             if any of the writes fail.
	 */
	protected abstract void applyUpdates(List<Ref> newRefs,
			List<ReceiveCommand> pending) throws IOException;

	private List<ReceiveCommand> getPending() {
		return ReceiveCommand.filter(getCommands(), NOT_ATTEMPTED);
	}

	private boolean checkObjectExistence(RevWalk rw,
			List<ReceiveCommand> pending) throws IOException {
		for (ReceiveCommand cmd : pending) {
			try {
				if (!cmd.getNewId().equals(ObjectId.zeroId())) {
					rw.parseAny(cmd.getNewId());
				}
			} catch (MissingObjectException e) {
				// ReceiveCommand#setResult(Result) converts REJECTED to
				// REJECTED_NONFASTFORWARD, even though that result is also
				// used for a missing object. Eagerly handle this case so we
				// can set the right result.
				cmd.setResult(REJECTED_MISSING_OBJECT);
				if (isAtomic()) {
					ReceiveCommand.abort(pending);
					return false;
				}
			}
		}
		return true;
	}

	private boolean checkNonFastForwards(RevWalk rw,
			List<ReceiveCommand> pending) throws IOException {
		if (isAllowNonFastForwards()) {
			return true;
		}
		for (ReceiveCommand cmd : pending) {
			cmd.updateType(rw);
			if (cmd.getType() == UPDATE_NONFASTFORWARD) {
				cmd.setResult(REJECTED_NONFASTFORWARD);
				if (isAtomic()) {
					ReceiveCommand.abort(pending);
					return false;
				}
			}
		}
		return true;
	}

	private boolean checkConflicting(List<ReceiveCommand> pending)
			throws IOException {
		TreeSet<String> added = new TreeSet<>();
		Set<String> deleted =
				pending.stream()
						.filter(cmd -> cmd.getType() == DELETE)
						.map(c -> c.getRefName())
						.collect(Collectors.toSet());

		boolean ok = true;
		for (ReceiveCommand cmd : pending) {
			if (cmd.getType() == DELETE) {
				continue;
			}

			String name = cmd.getRefName();
			if (refDb.isNameConflicting(name, added, deleted)) {
				if (isAtomic()) {
					cmd.setResult(
							ReceiveCommand.Result.REJECTED_OTHER_REASON, JGitText.get().transactionAborted);
				} else {
					cmd.setResult(LOCK_FAILURE);
				}

				ok = false;
			}
			added.add(name);
		}

		if (isAtomic()) {
			if (!ok) {
				pending.stream()
						.filter(cmd -> cmd.getResult() == NOT_ATTEMPTED)
						.forEach(cmd -> cmd.setResult(LOCK_FAILURE));
			}
			return ok;
		}

		for (ReceiveCommand cmd : pending) {
			if (cmd.getResult() == NOT_ATTEMPTED) {
				return true;
			}
		}

		return false;
	}

	private boolean checkExpected(List<ReceiveCommand> pending)
			throws IOException {
		for (ReceiveCommand cmd : pending) {
			if (!matchOld(cmd, refDb.exactRef(cmd.getRefName()))) {
				cmd.setResult(LOCK_FAILURE);
				if (isAtomic()) {
					ReceiveCommand.abort(pending);
					return false;
				}
			}
		}
		return true;
	}

	private static boolean matchOld(ReceiveCommand cmd, @Nullable Ref ref) {
		if (ref == null) {
			return AnyObjectId.isEqual(ObjectId.zeroId(), cmd.getOldId())
				&& cmd.getOldSymref() == null;
		} else if (ref.isSymbolic()) {
			return ref.getTarget().getName().equals(cmd.getOldSymref());
		}
		ObjectId id = ref.getObjectId();
		if (id == null) {
			id = ObjectId.zeroId();
		}
		return cmd.getOldId().equals(id);
	}

	/**
	 * Writes the refs to the writer, and calls finish.
	 *
	 * @param writer
	 *            the writer on which we should write.
	 * @param newRefs
	 *            the ref data to write..
	 * @param pending
	 *            the log data to write.
	 * @throws IOException
	 *            in case of problems.
	 */
	protected void write(ReftableWriter writer, List<Ref> newRefs,
			List<ReceiveCommand> pending) throws IOException {
		long updateIndex = refDb.nextUpdateIndex();
		writer.setMinUpdateIndex(updateIndex).setMaxUpdateIndex(updateIndex)
				.begin().sortAndWriteRefs(newRefs);
		if (!isRefLogDisabled()) {
			writeLog(writer, updateIndex, pending);
		}
	}

	private void writeLog(ReftableWriter writer, long updateIndex,
			List<ReceiveCommand> pending) throws IOException {
		Map<String, ReceiveCommand> cmds = new HashMap<>();
		List<String> byName = new ArrayList<>(pending.size());
		for (ReceiveCommand cmd : pending) {
			cmds.put(cmd.getRefName(), cmd);
			byName.add(cmd.getRefName());
		}
		Collections.sort(byName);

		PersonIdent ident = getRefLogIdent();
		if (ident == null) {
			ident = new PersonIdent(repository);
		}
		for (String name : byName) {
			ReceiveCommand cmd = cmds.get(name);
			if (isRefLogDisabled(cmd)) {
				continue;
			}
			String msg = getRefLogMessage(cmd);
			if (isRefLogIncludingResult(cmd)) {
				String strResult = toResultString(cmd);
				if (strResult != null) {
					msg = msg.isEmpty() ? strResult : msg + ": " + strResult; //$NON-NLS-1$
				}
			}
			writer.writeLog(name, updateIndex, ident, cmd.getOldId(),
					cmd.getNewId(), msg);
		}
	}

	private String toResultString(ReceiveCommand cmd) {
		switch (cmd.getType()) {
		case CREATE:
			return ReflogEntry.PREFIX_CREATED;
		case UPDATE:
			// Match the behavior of a single RefUpdate. In that case, setting
			// the force bit completely bypasses the potentially expensive
			// isMergedInto check, by design, so the reflog message may be
			// inaccurate.
			//
			// Similarly, this class bypasses the isMergedInto checks when the
			// force bit is set, meaning we can't actually distinguish between
			// UPDATE and UPDATE_NONFASTFORWARD when isAllowNonFastForwards()
			// returns true.
			return isAllowNonFastForwards() ? ReflogEntry.PREFIX_FORCED_UPDATE
					: ReflogEntry.PREFIX_FAST_FORWARD;
		case UPDATE_NONFASTFORWARD:
			return ReflogEntry.PREFIX_FORCED_UPDATE;
		default:
			return null;
		}
	}

	// Extracts and peels the refs out of the ReceiveCommands
	private static List<Ref> toNewRefs(RevWalk rw, List<ReceiveCommand> pending)
		throws IOException {
		List<Ref> refs = new ArrayList<>(pending.size());
		for (ReceiveCommand cmd : pending) {
			if (cmd.getResult() != NOT_ATTEMPTED) {
				continue;
			}

			String name = cmd.getRefName();
			ObjectId newId = cmd.getNewId();
			String newSymref = cmd.getNewSymref();
			if (AnyObjectId.isEqual(ObjectId.zeroId(), newId)
				&& newSymref == null) {
				refs.add(new ObjectIdRef.Unpeeled(NEW, name, null));
				continue;
			} else if (newSymref != null) {
				refs.add(new SymbolicRef(name,
					new ObjectIdRef.Unpeeled(NEW, newSymref, null)));
				continue;
			}

			RevObject obj = rw.parseAny(newId);
			RevObject peel = null;
			if (obj instanceof RevTag) {
				peel = rw.peel(obj);
			}
			if (peel != null) {
				refs.add(new ObjectIdRef.PeeledTag(PACKED, name, newId,
					peel.copy()));
			} else {
				refs.add(new ObjectIdRef.PeeledNonTag(PACKED, name, newId));
			}
		}
		return refs;
	}
}
