/*
 * Copyright (C) 2011, 2013 Google Inc., and others. 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.dfs;

import static org.eclipse.jgit.internal.storage.pack.PackExt.PACK;
import static org.eclipse.jgit.internal.storage.pack.PackExt.REFTABLE;

import java.util.Arrays;
import java.util.Comparator;

import org.eclipse.jgit.annotations.NonNull;
import org.eclipse.jgit.internal.storage.dfs.DfsObjDatabase.PackSource;
import org.eclipse.jgit.internal.storage.pack.PackExt;
import org.eclipse.jgit.internal.storage.reftable.ReftableWriter;
import org.eclipse.jgit.storage.pack.PackStatistics;

/**
 * Description of a DFS stored pack/index file.
 * <p>
 * Implementors may extend this class and add additional data members.
 * <p>
 * Instances of this class are cached with the DfsPackFile, and should not be
 * modified once initialized and presented to the JGit DFS library.
 */
public class DfsPackDescription {
	/**
	 * Comparator for packs when looking up objects in indexes.
	 * <p>
	 * This comparator tries to position packs in the order readers should examine
	 * them when looking for objects by SHA-1. The default tries to sort packs
	 * with more recent modification dates before older packs, and packs with
	 * fewer objects before packs with more objects.
	 * <p>
	 * Uses {@link PackSource#DEFAULT_COMPARATOR} for the portion of comparison
	 * where packs are sorted by source.
	 *
	 * @return comparator.
	 */
	public static Comparator<DfsPackDescription> objectLookupComparator() {
		return objectLookupComparator(PackSource.DEFAULT_COMPARATOR);
	}

	/**
	 * Comparator for packs when looking up objects in indexes.
	 * <p>
	 * This comparator tries to position packs in the order readers should examine
	 * them when looking for objects by SHA-1. The default tries to sort packs
	 * with more recent modification dates before older packs, and packs with
	 * fewer objects before packs with more objects.
	 *
	 * @param packSourceComparator
	 *            comparator for the {@link PackSource}, used as the first step in
	 *            comparison.
	 * @return comparator.
	 */
	public static Comparator<DfsPackDescription> objectLookupComparator(
			Comparator<PackSource> packSourceComparator) {
		return Comparator.comparing(
					DfsPackDescription::getPackSource, packSourceComparator)
			.thenComparing((a, b) -> {
				PackSource as = a.getPackSource();
				PackSource bs = b.getPackSource();

				// Tie break GC type packs by smallest first. There should be at most
				// one of each source, but when multiple exist concurrent GCs may have
				// run. Preferring the smaller file selects higher quality delta
				// compression, placing less demand on the DfsBlockCache.
				if (as == bs && isGC(as)) {
					int cmp = Long.signum(a.getFileSize(PACK) - b.getFileSize(PACK));
					if (cmp != 0) {
						return cmp;
					}
				}

				// Newer packs should sort first.
				int cmp = Long.signum(b.getLastModified() - a.getLastModified());
				if (cmp != 0) {
					return cmp;
				}

				// Break ties on smaller index. Readers may get lucky and find
				// the object they care about in the smaller index. This also pushes
				// big historical packs to the end of the list, due to more objects.
				return Long.signum(a.getObjectCount() - b.getObjectCount());
			});
	}

	static Comparator<DfsPackDescription> reftableComparator() {
		return (a, b) -> {
				// GC, COMPACT reftables first by reversing default order.
				int c = PackSource.DEFAULT_COMPARATOR.reversed()
						.compare(a.getPackSource(), b.getPackSource());
				if (c != 0) {
					return c;
				}

				// Lower maxUpdateIndex first.
				c = Long.signum(a.getMaxUpdateIndex() - b.getMaxUpdateIndex());
				if (c != 0) {
					return c;
				}

				// Older reftable first.
				return Long.signum(a.getLastModified() - b.getLastModified());
			};
	}

	static Comparator<DfsPackDescription> reuseComparator() {
		return (a, b) -> {
			PackSource as = a.getPackSource();
			PackSource bs = b.getPackSource();

			if (as == bs && DfsPackDescription.isGC(as)) {
				// Push smaller GC files last; these likely have higher quality
				// delta compression and the contained representation should be
				// favored over other files.
				return Long.signum(b.getFileSize(PACK) - a.getFileSize(PACK));
			}

			// DfsPackDescription.compareTo already did a reasonable sort.
			// Rely on Arrays.sort being stable, leaving equal elements.
			return 0;
		};
	}

	private final DfsRepositoryDescription repoDesc;
	private final String packName;
	private PackSource packSource;
	private long lastModified;
	private long[] sizeMap;
	private int[] blockSizeMap;
	private long objectCount;
	private long deltaCount;
	private long minUpdateIndex;
	private long maxUpdateIndex;

	private PackStatistics packStats;
	private ReftableWriter.Stats refStats;
	private int extensions;
	private int indexVersion;
	private long estimatedPackSize;

	/**
	 * Initialize a description by pack name and repository.
	 * <p>
	 * The corresponding index file is assumed to exist. If this is not true
	 * implementors must extend the class and override
	 * {@link #getFileName(PackExt)}.
	 * <p>
	 * Callers should also try to fill in other fields if they are reasonably
	 * free to access at the time this instance is being initialized.
	 *
	 * @param name
	 *            name of the pack file. Must end with ".pack".
	 * @param repoDesc
	 *            description of the repo containing the pack file.
	 * @param packSource
	 *            the source of the pack.
	 */
	public DfsPackDescription(DfsRepositoryDescription repoDesc, String name,
			@NonNull PackSource packSource) {
		this.repoDesc = repoDesc;
		int dot = name.lastIndexOf('.');
		this.packName = (dot < 0) ? name : name.substring(0, dot);
		this.packSource = packSource;

		int extCnt = PackExt.values().length;
		sizeMap = new long[extCnt];
		blockSizeMap = new int[extCnt];
	}

	/**
	 * Get description of the repository.
	 *
	 * @return description of the repository.
	 */
	public DfsRepositoryDescription getRepositoryDescription() {
		return repoDesc;
	}

	/**
	 * Adds the pack file extension to the known list.
	 *
	 * @param ext
	 *            the file extension
	 */
	public void addFileExt(PackExt ext) {
		extensions |= ext.getBit();
	}

	/**
	 * Whether the pack file extension is known to exist.
	 *
	 * @param ext
	 *            the file extension
	 * @return whether the pack file extension is known to exist.
	 */
	public boolean hasFileExt(PackExt ext) {
		return (extensions & ext.getBit()) != 0;
	}

	/**
	 * Get file name
	 *
	 * @param ext
	 *            the file extension
	 * @return name of the file.
	 */
	public String getFileName(PackExt ext) {
		return packName + '.' + ext.getExtension();
	}

	/**
	 * Get cache key for use by the block cache.
	 *
	 * @param ext
	 *            the file extension.
	 * @return cache key for use by the block cache.
	 */
	public DfsStreamKey getStreamKey(PackExt ext) {
		return DfsStreamKey.of(getRepositoryDescription(), getFileName(ext),
				ext);
	}

	/**
	 * Get the source of the pack.
	 *
	 * @return the source of the pack.
	 */
	@NonNull
	public PackSource getPackSource() {
		return packSource;
	}

	/**
	 * Set the source of the pack.
	 *
	 * @param source
	 *            the source of the pack.
	 * @return {@code this}
	 */
	public DfsPackDescription setPackSource(@NonNull PackSource source) {
		packSource = source;
		return this;
	}

	/**
	 * Get time the pack was created, in milliseconds.
	 *
	 * @return time the pack was created, in milliseconds.
	 */
	public long getLastModified() {
		return lastModified;
	}

	/**
	 * Set time the pack was created, in milliseconds.
	 *
	 * @param timeMillis
	 *            time the pack was created, in milliseconds. 0 if not known.
	 * @return {@code this}
	 */
	public DfsPackDescription setLastModified(long timeMillis) {
		lastModified = timeMillis;
		return this;
	}

	/**
	 * Get minUpdateIndex for the reftable, if present.
	 *
	 * @return minUpdateIndex for the reftable, if present.
	 */
	public long getMinUpdateIndex() {
		return minUpdateIndex;
	}

	/**
	 * Set minUpdateIndex for the reftable.
	 *
	 * @param min
	 *            minUpdateIndex for the reftable.
	 * @return {@code this}
	 */
	public DfsPackDescription setMinUpdateIndex(long min) {
		minUpdateIndex = min;
		return this;
	}

	/**
	 * Get maxUpdateIndex for the reftable, if present.
	 *
	 * @return maxUpdateIndex for the reftable, if present.
	 */
	public long getMaxUpdateIndex() {
		return maxUpdateIndex;
	}

	/**
	 * Set maxUpdateIndex for the reftable.
	 *
	 * @param max
	 *            maxUpdateIndex for the reftable.
	 * @return {@code this}
	 */
	public DfsPackDescription setMaxUpdateIndex(long max) {
		maxUpdateIndex = max;
		return this;
	}

	/**
	 * Set size of the file in bytes.
	 *
	 * @param ext
	 *            the file extension.
	 * @param bytes
	 *            size of the file in bytes. If 0 the file is not known and will
	 *            be determined on first read.
	 * @return {@code this}
	 */
	public DfsPackDescription setFileSize(PackExt ext, long bytes) {
		int i = ext.getPosition();
		if (i >= sizeMap.length) {
			sizeMap = Arrays.copyOf(sizeMap, i + 1);
		}
		sizeMap[i] = Math.max(0, bytes);
		return this;
	}

	/**
	 * Get size of the file, in bytes.
	 *
	 * @param ext
	 *            the file extension.
	 * @return size of the file, in bytes. If 0 the file size is not yet known.
	 */
	public long getFileSize(PackExt ext) {
		int i = ext.getPosition();
		return i < sizeMap.length ? sizeMap[i] : 0;
	}

	/**
	 * Get blockSize of the file, in bytes.
	 *
	 * @param ext
	 *            the file extension.
	 * @return blockSize of the file, in bytes. If 0 the blockSize size is not
	 *         yet known and may be discovered when opening the file.
	 */
	public int getBlockSize(PackExt ext) {
		int i = ext.getPosition();
		return i < blockSizeMap.length ? blockSizeMap[i] : 0;
	}

	/**
	 * Set blockSize of the file, in bytes.
	 *
	 * @param ext
	 *            the file extension.
	 * @param blockSize
	 *            blockSize of the file, in bytes. If 0 the blockSize is not
	 *            known and will be determined on first read.
	 * @return {@code this}
	 */
	public DfsPackDescription setBlockSize(PackExt ext, int blockSize) {
		int i = ext.getPosition();
		if (i >= blockSizeMap.length) {
			blockSizeMap = Arrays.copyOf(blockSizeMap, i + 1);
		}
		blockSizeMap[i] = Math.max(0, blockSize);
		return this;
	}

	/**
	 * Set estimated size of the .pack file in bytes.
	 *
	 * @param estimatedPackSize
	 *            estimated size of the .pack file in bytes. If 0 the pack file
	 *            size is unknown.
	 * @return {@code this}
	 */
	public DfsPackDescription setEstimatedPackSize(long estimatedPackSize) {
		this.estimatedPackSize = Math.max(0, estimatedPackSize);
		return this;
	}

	/**
	 * Get estimated size of the .pack file in bytes.
	 *
	 * @return estimated size of the .pack file in bytes. If 0 the pack file
	 *         size is unknown.
	 */
	public long getEstimatedPackSize() {
		return estimatedPackSize;
	}

	/**
	 * Get number of objects in the pack.
	 *
	 * @return number of objects in the pack.
	 */
	public long getObjectCount() {
		return objectCount;
	}

	/**
	 * Set number of objects in the pack.
	 *
	 * @param cnt
	 *            number of objects in the pack.
	 * @return {@code this}
	 */
	public DfsPackDescription setObjectCount(long cnt) {
		objectCount = Math.max(0, cnt);
		return this;
	}

	/**
	 * Get number of delta compressed objects in the pack.
	 *
	 * @return number of delta compressed objects in the pack.
	 */
	public long getDeltaCount() {
		return deltaCount;
	}

	/**
	 * Set number of delta compressed objects in the pack.
	 *
	 * @param cnt
	 *            number of delta compressed objects in the pack.
	 * @return {@code this}
	 */
	public DfsPackDescription setDeltaCount(long cnt) {
		deltaCount = Math.max(0, cnt);
		return this;
	}

	/**
	 * Get statistics from PackWriter, if the pack was built with it.
	 *
	 * @return statistics from PackWriter, if the pack was built with it.
	 *         Generally this is only available for packs created by
	 *         DfsGarbageCollector or DfsPackCompactor, and only when the pack
	 *         is being committed to the repository.
	 */
	public PackStatistics getPackStats() {
		return packStats;
	}

	DfsPackDescription setPackStats(PackStatistics stats) {
		this.packStats = stats;
		setFileSize(PACK, stats.getTotalBytes());
		setObjectCount(stats.getTotalObjects());
		setDeltaCount(stats.getTotalDeltas());
		return this;
	}

	/**
	 * Get stats from the sibling reftable, if created.
	 *
	 * @return stats from the sibling reftable, if created.
	 */
	public ReftableWriter.Stats getReftableStats() {
		return refStats;
	}

	void setReftableStats(ReftableWriter.Stats stats) {
		this.refStats = stats;
		setMinUpdateIndex(stats.minUpdateIndex());
		setMaxUpdateIndex(stats.maxUpdateIndex());
		setFileSize(REFTABLE, stats.totalBytes());
		setBlockSize(REFTABLE, stats.refBlockSize());
	}

	/**
	 * Discard the pack statistics, if it was populated.
	 *
	 * @return {@code this}
	 */
	public DfsPackDescription clearPackStats() {
		packStats = null;
		refStats = null;
		return this;
	}

	/**
	 * Get the version of the index file written.
	 *
	 * @return the version of the index file written.
	 */
	public int getIndexVersion() {
		return indexVersion;
	}

	/**
	 * Set the version of the index file written.
	 *
	 * @param version
	 *            the version of the index file written.
	 * @return {@code this}
	 */
	public DfsPackDescription setIndexVersion(int version) {
		indexVersion = version;
		return this;
	}

	/** {@inheritDoc} */
	@Override
	public int hashCode() {
		return packName.hashCode();
	}

	/** {@inheritDoc} */
	@Override
	public boolean equals(Object b) {
		if (b instanceof DfsPackDescription) {
			DfsPackDescription desc = (DfsPackDescription) b;
			return packName.equals(desc.packName) &&
					getRepositoryDescription().equals(desc.getRepositoryDescription());
		}
		return false;
	}

	static boolean isGC(PackSource s) {
		switch (s) {
		case GC:
		case GC_REST:
		case GC_TXN:
			return true;
		default:
			return false;
		}
	}

	/** {@inheritDoc} */
	@Override
	public String toString() {
		return getFileName(PackExt.PACK);
	}
}
