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

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.StandardCopyOption;
import java.text.MessageFormat;
import java.util.Set;

import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.storage.file.FileObjectDatabase.InsertLooseObjectResult;
import org.eclipse.jgit.lib.AbbreviatedObjectId;
import org.eclipse.jgit.lib.AnyObjectId;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.util.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Traditional file system based loose objects handler.
 * <p>
 * This is the loose object representation for a Git object database, where
 * objects are stored loose by hashing them into directories by their
 * {@link org.eclipse.jgit.lib.ObjectId}.
 */
class LooseObjects {
	private static final Logger LOG = LoggerFactory
			.getLogger(LooseObjects.class);

	/**
	 * Maximum number of attempts to read a loose object for which a stale file
	 * handle exception is thrown
	 */
	private final static int MAX_LOOSE_OBJECT_STALE_READ_ATTEMPTS = 5;

	private final File directory;

	private final UnpackedObjectCache unpackedObjectCache;

	private final boolean trustFolderStat;

	/**
	 * Initialize a reference to an on-disk object directory.
	 *
	 * @param config
	 *            configuration for the loose objects handler.
	 * @param dir
	 *            the location of the <code>objects</code> directory.
	 */
	LooseObjects(Config config, File dir) {
		directory = dir;
		unpackedObjectCache = new UnpackedObjectCache();
		trustFolderStat = config.getBoolean(
				ConfigConstants.CONFIG_CORE_SECTION,
				ConfigConstants.CONFIG_KEY_TRUSTFOLDERSTAT, true);
	}

	/**
	 * Getter for the field <code>directory</code>.
	 *
	 * @return the location of the <code>objects</code> directory.
	 */
	File getDirectory() {
		return directory;
	}

	void create() throws IOException {
		FileUtils.mkdirs(directory);
	}

	void close() {
		unpackedObjectCache().clear();
	}

	@Override
	public String toString() {
		return "LooseObjects[" + directory + "]"; //$NON-NLS-1$ //$NON-NLS-2$
	}

	boolean hasCached(AnyObjectId id) {
		return unpackedObjectCache().isUnpacked(id);
	}

	/**
	 * Does the requested object exist as a loose object?
	 *
	 * @param objectId
	 *            identity of the object to test for existence of.
	 * @return {@code true} if the specified object is stored as a loose object.
	 */
	boolean has(AnyObjectId objectId) {
		boolean exists = hasWithoutRefresh(objectId);
		if (trustFolderStat || exists) {
			return exists;
		}
		try (InputStream stream = Files.newInputStream(directory.toPath())) {
			// refresh directory to work around NFS caching issue
		} catch (IOException e) {
			return false;
		}
		return hasWithoutRefresh(objectId);
	}

	private boolean hasWithoutRefresh(AnyObjectId objectId) {
		return fileFor(objectId).exists();
	}

	/**
	 * Find objects matching the prefix abbreviation.
	 *
	 * @param matches
	 *            set to add any located ObjectIds to. This is an output
	 *            parameter.
	 * @param id
	 *            prefix to search for.
	 * @param matchLimit
	 *            maximum number of results to return. At most this many
	 *            ObjectIds should be added to matches before returning.
	 * @return {@code true} if the matches were exhausted before reaching
	 *         {@code maxLimit}.
	 */
	boolean resolve(Set<ObjectId> matches, AbbreviatedObjectId id,
			int matchLimit) {
		String fanOut = id.name().substring(0, 2);
		String[] entries = new File(directory, fanOut).list();
		if (entries != null) {
			for (String e : entries) {
				if (e.length() != Constants.OBJECT_ID_STRING_LENGTH - 2) {
					continue;
				}
				try {
					ObjectId entId = ObjectId.fromString(fanOut + e);
					if (id.prefixCompare(entId) == 0) {
						matches.add(entId);
					}
				} catch (IllegalArgumentException notId) {
					continue;
				}
				if (matches.size() > matchLimit) {
					return false;
				}
			}
		}
		return true;
	}

	ObjectLoader open(WindowCursor curs, AnyObjectId id) throws IOException {
		int readAttempts = 0;
		while (readAttempts < MAX_LOOSE_OBJECT_STALE_READ_ATTEMPTS) {
			readAttempts++;
			File path = fileFor(id);
			try {
				return getObjectLoader(curs, path, id);
			} catch (FileNotFoundException noFile) {
				if (path.exists()) {
					throw noFile;
				}
				break;
			} catch (IOException e) {
				if (!FileUtils.isStaleFileHandleInCausalChain(e)) {
					throw e;
				}
				if (LOG.isDebugEnabled()) {
					LOG.debug(MessageFormat.format(
							JGitText.get().looseObjectHandleIsStale, id.name(),
							Integer.valueOf(readAttempts), Integer.valueOf(
									MAX_LOOSE_OBJECT_STALE_READ_ATTEMPTS)));
				}
			}
		}
		unpackedObjectCache().remove(id);
		return null;
	}

	/**
	 * Provides a loader for an objectId
	 *
	 * @param curs
	 *            cursor on the database
	 * @param path
	 *            the path of the loose object
	 * @param id
	 *            the object id
	 * @return a loader for the loose file object
	 * @throws IOException
	 *             when file does not exist or it could not be opened
	 */
	ObjectLoader getObjectLoader(WindowCursor curs, File path, AnyObjectId id)
			throws IOException {
		try {
			return getObjectLoaderWithoutRefresh(curs, path, id);
		} catch (FileNotFoundException e) {
			if (trustFolderStat) {
				throw e;
			}
			try (InputStream stream = Files
					.newInputStream(directory.toPath())) {
				// refresh directory to work around NFS caching issues
			}
			return getObjectLoaderWithoutRefresh(curs, path, id);
		}
	}

	private ObjectLoader getObjectLoaderWithoutRefresh(WindowCursor curs,
			File path, AnyObjectId id) throws IOException {
		try (FileInputStream in = new FileInputStream(path)) {
			unpackedObjectCache().add(id);
			return UnpackedObject.open(in, path, id, curs);
		}
	}

	/**
	 * <p>
	 * Getter for the field <code>unpackedObjectCache</code>.
	 * </p>
	 * This accessor is particularly useful to allow mocking of this class for
	 * testing purposes.
	 *
	 * @return the cache of the objects currently unpacked.
	 */
	UnpackedObjectCache unpackedObjectCache() {
		return unpackedObjectCache;
	}

	long getSize(WindowCursor curs, AnyObjectId id) throws IOException {
		try {
			return getSizeWithoutRefresh(curs, id);
		} catch (FileNotFoundException noFile) {
			try {
				if (trustFolderStat) {
					throw noFile;
				}
				try (InputStream stream = Files
						.newInputStream(directory.toPath())) {
					// refresh directory to work around NFS caching issue
				}
				return getSizeWithoutRefresh(curs, id);
			} catch (FileNotFoundException unused) {
				if (fileFor(id).exists()) {
					throw noFile;
				}
				unpackedObjectCache().remove(id);
				return -1;
			}
		}
	}

	private long getSizeWithoutRefresh(WindowCursor curs, AnyObjectId id)
			throws IOException {
		File f = fileFor(id);
		try (FileInputStream in = new FileInputStream(f)) {
			unpackedObjectCache().add(id);
			return UnpackedObject.getSize(in, id, curs);
		}
	}

	InsertLooseObjectResult insert(File tmp, ObjectId id) throws IOException {
		final File dst = fileFor(id);
		if (dst.exists()) {
			// We want to be extra careful and avoid replacing an object
			// that already exists. We can't be sure renameTo() would
			// fail on all platforms if dst exists, so we check first.
			//
			FileUtils.delete(tmp, FileUtils.RETRY);
			return InsertLooseObjectResult.EXISTS_LOOSE;
		}

		try {
			return tryMove(tmp, dst, id);
		} catch (NoSuchFileException e) {
			// It's possible the directory doesn't exist yet as the object
			// directories are always lazily created. Note that we try the
			// rename/move first as the directory likely does exist.
			//
			// Create the directory.
			//
			FileUtils.mkdir(dst.getParentFile(), true);
		} catch (IOException e) {
			// Any other IO error is considered a failure.
			//
			LOG.error(e.getMessage(), e);
			FileUtils.delete(tmp, FileUtils.RETRY);
			return InsertLooseObjectResult.FAILURE;
		}

		try {
			return tryMove(tmp, dst, id);
		} catch (IOException e) {
			// The object failed to be renamed into its proper location and
			// it doesn't exist in the repository either. We really don't
			// know what went wrong, so fail.
			//
			LOG.error(e.getMessage(), e);
			FileUtils.delete(tmp, FileUtils.RETRY);
			return InsertLooseObjectResult.FAILURE;
		}
	}

	private InsertLooseObjectResult tryMove(File tmp, File dst, ObjectId id)
			throws IOException {
		Files.move(FileUtils.toPath(tmp), FileUtils.toPath(dst),
				StandardCopyOption.ATOMIC_MOVE);
		dst.setReadOnly();
		unpackedObjectCache().add(id);
		return InsertLooseObjectResult.INSERTED;
	}

	/**
	 * Compute the location of a loose object file.
	 *
	 * @param objectId
	 *            identity of the object to get the File location for.
	 * @return {@link java.io.File} location of the specified loose object.
	 */
	File fileFor(AnyObjectId objectId) {
		String n = objectId.name();
		String d = n.substring(0, 2);
		String f = n.substring(2);
		return new File(new File(getDirectory(), d), f);
	}
}
