/*
 * Copyright (C) 2021, Tencent.
 *
 * 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.commitgraph;

import java.io.IOException;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdOwnerMap;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevObject;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.BlockList;

/**
 * The commits which are used by the commit-graph writer to:
 * <ul>
 * <li>List commits in SHA1 order.</li>
 * <li>Get the position of a specific SHA1 in the list.</li>
 * </ul>
 *
 * @since 6.5
 */
public class GraphCommits implements Iterable<RevCommit> {

	/**
	 * Prepare and create the commits for
	 * {@link org.eclipse.jgit.internal.storage.commitgraph.CommitGraphWriter}
	 * from the RevWalk.
	 *
	 * @param pm
	 *            progress monitor.
	 * @param wants
	 *            the list of wanted objects, writer walks commits starting at
	 *            these. Must not be {@code null}.
	 * @param walk
	 *            the RevWalk to use. Must not be {@code null}.
	 * @return the commits' collection which are used by the commit-graph
	 *         writer. Never null.
	 * @throws IOException
	 */
	public static GraphCommits fromWalk(ProgressMonitor pm,
			@NonNull Set<? extends ObjectId> wants, @NonNull RevWalk walk)
			throws IOException {
		walk.reset();
		walk.sort(RevSort.NONE);
		walk.setRetainBody(false);
		for (ObjectId id : wants) {
			RevObject o = walk.parseAny(id);
			if (o instanceof RevCommit) {
				walk.markStart((RevCommit) o);
			}
		}
		List<RevCommit> commits = new BlockList<>();
		RevCommit c;
		pm.beginTask(JGitText.get().findingCommitsForCommitGraph,
				ProgressMonitor.UNKNOWN);
		while ((c = walk.next()) != null) {
			pm.update(1);
			commits.add(c);
		}
		pm.endTask();
		return new GraphCommits(commits);
	}

	private final List<RevCommit> sortedCommits;

	private final ObjectIdOwnerMap<CommitWithPosition> commitPosMap;

	private final int extraEdgeCnt;

	/**
	 * Initialize the GraphCommits.
	 *
	 * @param commits
	 *            list of commits with their headers already parsed.
	 */
	private GraphCommits(List<RevCommit> commits) {
		Collections.sort(commits); // sorted by name
		sortedCommits = commits;
		commitPosMap = new ObjectIdOwnerMap<>();
		int cnt = 0;
		for (int i = 0; i < commits.size(); i++) {
			RevCommit c = sortedCommits.get(i);
			if (c.getParentCount() > 2) {
				cnt += c.getParentCount() - 1;
			}
			commitPosMap.add(new CommitWithPosition(c, i));
		}
		this.extraEdgeCnt = cnt;
	}

	int getOidPosition(RevCommit c) throws MissingObjectException {
		CommitWithPosition commitWithPosition = commitPosMap.get(c);
		if (commitWithPosition == null) {
			throw new MissingObjectException(c, Constants.OBJ_COMMIT);
		}
		return commitWithPosition.position;
	}

	int getExtraEdgeCnt() {
		return extraEdgeCnt;
	}

	int size() {
		return sortedCommits.size();
	}

	/** {@inheritDoc} */
	@Override
	public Iterator<RevCommit> iterator() {
		return sortedCommits.iterator();
	}

	private static class CommitWithPosition extends ObjectIdOwnerMap.Entry {

		final int position;

		CommitWithPosition(AnyObjectId id, int position) {
			super(id);
			this.position = position;
		}
	}
}
