/*
 * Copyright (C) 2008, 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.dircache;

import static org.eclipse.jgit.lib.FileMode.TYPE_TREE;
import static org.eclipse.jgit.util.Paths.compareSameName;

import java.io.IOException;

import org.eclipse.jgit.errors.DirCacheNameConflictException;

/**
 * Generic update/editing support for {@link DirCache}.
 * <p>
 * The different update strategies extend this class to provide their own unique
 * services to applications.
 */
abstract class BaseDirCacheEditor {
	/** The cache instance this editor updates during {@link #finish()}. */
	protected DirCache cache;

	/**
	 * Entry table this builder will eventually replace into {@link #cache}.
	 * <p>
	 * Use {@link #fastAdd(DirCacheEntry)} or {@link #fastKeep(int, int)} to
	 * make additions to this table. The table is automatically expanded if it
	 * is too small for a new addition.
	 * <p>
	 * Typically the entries in here are sorted by their path names, just like
	 * they are in the DirCache instance.
	 */
	protected DirCacheEntry[] entries;

	/** Total number of valid entries in {@link #entries}. */
	protected int entryCnt;

	/**
	 * Construct a new editor.
	 *
	 * @param dc
	 *            the cache this editor will eventually update.
	 * @param ecnt
	 *            estimated number of entries the editor will have upon
	 *            completion. This sizes the initial entry table.
	 */
	protected BaseDirCacheEditor(DirCache dc, int ecnt) {
		cache = dc;
		entries = new DirCacheEntry[ecnt];
	}

	/**
	 * Get the {@code DirCache}
	 *
	 * @return the cache we will update on {@link #finish()}.
	 */
	public DirCache getDirCache() {
		return cache;
	}

	/**
	 * Append one entry into the resulting entry list.
	 * <p>
	 * The entry is placed at the end of the entry list. The caller is
	 * responsible for making sure the final table is correctly sorted.
	 * <p>
	 * The {@link #entries} table is automatically expanded if there is
	 * insufficient space for the new addition.
	 *
	 * @param newEntry
	 *            the new entry to add.
	 */
	protected void fastAdd(DirCacheEntry newEntry) {
		if (entries.length == entryCnt) {
			final DirCacheEntry[] n = new DirCacheEntry[(entryCnt + 16) * 3 / 2];
			System.arraycopy(entries, 0, n, 0, entryCnt);
			entries = n;
		}
		entries[entryCnt++] = newEntry;
	}

	/**
	 * Add a range of existing entries from the destination cache.
	 * <p>
	 * The entries are placed at the end of the entry list, preserving their
	 * current order. The caller is responsible for making sure the final table
	 * is correctly sorted.
	 * <p>
	 * This method copies from the destination cache, which has not yet been
	 * updated with this editor's new table. So all offsets into the destination
	 * cache are not affected by any updates that may be currently taking place
	 * in this editor.
	 * <p>
	 * The {@link #entries} table is automatically expanded if there is
	 * insufficient space for the new additions.
	 *
	 * @param pos
	 *            first entry to copy from the destination cache.
	 * @param cnt
	 *            number of entries to copy.
	 */
	protected void fastKeep(int pos, int cnt) {
		if (entryCnt + cnt > entries.length) {
			final int m1 = (entryCnt + 16) * 3 / 2;
			final int m2 = entryCnt + cnt;
			final DirCacheEntry[] n = new DirCacheEntry[Math.max(m1, m2)];
			System.arraycopy(entries, 0, n, 0, entryCnt);
			entries = n;
		}

		cache.toArray(pos, entries, entryCnt, cnt);
		entryCnt += cnt;
	}

	/**
	 * Finish this builder and update the destination
	 * {@link org.eclipse.jgit.dircache.DirCache}.
	 * <p>
	 * When this method completes this builder instance is no longer usable by
	 * the calling application. A new builder must be created to make additional
	 * changes to the index entries.
	 * <p>
	 * After completion the DirCache returned by {@link #getDirCache()} will
	 * contain all modifications.
	 * <p>
	 * <i>Note to implementors:</i> Make sure {@link #entries} is fully sorted
	 * then invoke {@link #replace()} to update the DirCache with the new table.
	 */
	public abstract void finish();

	/**
	 * Update the DirCache with the contents of {@link #entries}.
	 * <p>
	 * This method should be invoked only during an implementation of
	 * {@link #finish()}, and only after {@link #entries} is sorted.
	 */
	protected void replace() {
		checkNameConflicts();
		if (entryCnt < entries.length / 2) {
			final DirCacheEntry[] n = new DirCacheEntry[entryCnt];
			System.arraycopy(entries, 0, n, 0, entryCnt);
			entries = n;
		}
		cache.replace(entries, entryCnt);
	}

	private void checkNameConflicts() {
		int end = entryCnt - 1;
		for (int eIdx = 0; eIdx < end; eIdx++) {
			DirCacheEntry e = entries[eIdx];
			if (e.getStage() != 0) {
				continue;
			}

			byte[] ePath = e.path;
			int prefixLen = lastSlash(ePath) + 1;

			for (int nIdx = eIdx + 1; nIdx < entryCnt; nIdx++) {
				DirCacheEntry n = entries[nIdx];
				if (n.getStage() != 0) {
					continue;
				}

				byte[] nPath = n.path;
				if (!startsWith(ePath, nPath, prefixLen)) {
					// Different prefix; this entry is in another directory.
					break;
				}

				int s = nextSlash(nPath, prefixLen);
				int m = s < nPath.length ? TYPE_TREE : n.getRawMode();
				int cmp = compareSameName(
						ePath, prefixLen, ePath.length,
						nPath, prefixLen, s, m);
				if (cmp < 0) {
					break;
				} else if (cmp == 0) {
					throw new DirCacheNameConflictException(
							e.getPathString(),
							n.getPathString());
				}
			}
		}
	}

	private static int lastSlash(byte[] path) {
		for (int i = path.length - 1; i >= 0; i--) {
			if (path[i] == '/') {
				return i;
			}
		}
		return -1;
	}

	private static int nextSlash(byte[] b, int p) {
		final int n = b.length;
		for (; p < n; p++) {
			if (b[p] == '/') {
				return p;
			}
		}
		return n;
	}

	private static boolean startsWith(byte[] a, byte[] b, int n) {
		if (b.length < n) {
			return false;
		}
		for (n--; n >= 0; n--) {
			if (a[n] != b[n]) {
				return false;
			}
		}
		return true;
	}

	/**
	 * Finish, write, commit this change, and release the index lock.
	 * <p>
	 * If this method fails (returns false) the lock is still released.
	 * <p>
	 * This is a utility method for applications as the finish-write-commit
	 * pattern is very common after using a builder to update entries.
	 *
	 * @return true if the commit was successful and the file contains the new
	 *         data; false if the commit failed and the file remains with the
	 *         old data.
	 * @throws java.lang.IllegalStateException
	 *             the lock is not held.
	 * @throws java.io.IOException
	 *             the output file could not be created. The caller no longer
	 *             holds the lock.
	 */
	public boolean commit() throws IOException {
		finish();
		cache.write();
		return cache.commit();
	}
}
