/*
 * Copyright (C) 2010, Google Inc.
 * and other copyright owners as documented in the project's IP log.
 *
 * This program and the accompanying materials are made available
 * under the terms of the Eclipse Distribution License v1.0 which
 * accompanies this distribution, is reproduced below, and is
 * available at http://www.eclipse.org/org/documents/edl-v10.php
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or
 * without modification, are permitted provided that the following
 * conditions are met:
 *
 * - Redistributions of source code must retain the above copyright
 *   notice, this list of conditions and the following disclaimer.
 *
 * - Redistributions in binary form must reproduce the above
 *   copyright notice, this list of conditions and the following
 *   disclaimer in the documentation and/or other materials provided
 *   with the distribution.
 *
 * - Neither the name of the Eclipse Foundation, Inc. nor the
 *   names of its contributors may be used to endorse or promote
 *   products derived from this software without specific prior
 *   written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

package org.eclipse.jgit.lib;

import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_CORE_SECTION;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_BARE;
import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_WORKTREE;
import static org.eclipse.jgit.lib.Constants.DOT_GIT;
import static org.eclipse.jgit.lib.Constants.GIT_ALTERNATE_OBJECT_DIRECTORIES_KEY;
import static org.eclipse.jgit.lib.Constants.GIT_CEILING_DIRECTORIES_KEY;
import static org.eclipse.jgit.lib.Constants.GIT_DIR_KEY;
import static org.eclipse.jgit.lib.Constants.GIT_INDEX_FILE_KEY;
import static org.eclipse.jgit.lib.Constants.GIT_OBJECT_DIRECTORY_KEY;
import static org.eclipse.jgit.lib.Constants.GIT_WORK_TREE_KEY;

import java.io.File;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;

import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.storage.file.FileRepository;
import org.eclipse.jgit.lib.RepositoryCache.FileKey;
import org.eclipse.jgit.storage.file.FileBasedConfig;
import org.eclipse.jgit.storage.file.FileRepositoryBuilder;
import org.eclipse.jgit.util.FS;
import org.eclipse.jgit.util.IO;
import org.eclipse.jgit.util.RawParseUtils;
import org.eclipse.jgit.util.SystemReader;

/**
 * Base builder to customize repository construction.
 * <p>
 * Repository implementations may subclass this builder in order to add custom
 * repository detection methods.
 *
 * @param <B>
 *            type of the repository builder.
 * @param <R>
 *            type of the repository that is constructed.
 * @see RepositoryBuilder
 * @see FileRepositoryBuilder
 */
public class BaseRepositoryBuilder<B extends BaseRepositoryBuilder, R extends Repository> {
	private static boolean isSymRef(byte[] ref) {
		if (ref.length < 9)
			return false;
		return /**/ref[0] == 'g' //
				&& ref[1] == 'i' //
				&& ref[2] == 't' //
				&& ref[3] == 'd' //
				&& ref[4] == 'i' //
				&& ref[5] == 'r' //
				&& ref[6] == ':' //
				&& ref[7] == ' ';
	}

	private static File getSymRef(File workTree, File dotGit, FS fs)
			throws IOException {
		byte[] content = IO.readFully(dotGit);
		if (!isSymRef(content))
			throw new IOException(MessageFormat.format(
					JGitText.get().invalidGitdirRef, dotGit.getAbsolutePath()));

		int pathStart = 8;
		int lineEnd = RawParseUtils.nextLF(content, pathStart);
		while (content[lineEnd - 1] == '\n' ||
		       (content[lineEnd - 1] == '\r' && SystemReader.getInstance().isWindows()))
			lineEnd--;
		if (lineEnd == pathStart)
			throw new IOException(MessageFormat.format(
					JGitText.get().invalidGitdirRef, dotGit.getAbsolutePath()));

		String gitdirPath = RawParseUtils.decode(content, pathStart, lineEnd);
		File gitdirFile = fs.resolve(workTree, gitdirPath);
		if (gitdirFile.isAbsolute())
			return gitdirFile;
		else
			return new File(workTree, gitdirPath).getCanonicalFile();
	}

	private FS fs;

	private File gitDir;

	private File objectDirectory;

	private List<File> alternateObjectDirectories;

	private File indexFile;

	private File workTree;

	/** Directories limiting the search for a Git repository. */
	private List<File> ceilingDirectories;

	/** True only if the caller wants to force bare behavior. */
	private boolean bare;

	/** True if the caller requires the repository to exist. */
	private boolean mustExist;

	/** Configuration file of target repository, lazily loaded if required. */
	private Config config;

	/**
	 * Set the file system abstraction needed by this repository.
	 *
	 * @param fs
	 *            the abstraction.
	 * @return {@code this} (for chaining calls).
	 */
	public B setFS(FS fs) {
		this.fs = fs;
		return self();
	}

	/** @return the file system abstraction, or null if not set. */
	public FS getFS() {
		return fs;
	}

	/**
	 * Set the Git directory storing the repository metadata.
	 * <p>
	 * The meta directory stores the objects, references, and meta files like
	 * {@code MERGE_HEAD}, or the index file. If {@code null} the path is
	 * assumed to be {@code workTree/.git}.
	 *
	 * @param gitDir
	 *            {@code GIT_DIR}, the repository meta directory.
	 * @return {@code this} (for chaining calls).
	 */
	public B setGitDir(File gitDir) {
		this.gitDir = gitDir;
		this.config = null;
		return self();
	}

	/** @return the meta data directory; null if not set. */
	public File getGitDir() {
		return gitDir;
	}

	/**
	 * Set the directory storing the repository's objects.
	 *
	 * @param objectDirectory
	 *            {@code GIT_OBJECT_DIRECTORY}, the directory where the
	 *            repository's object files are stored.
	 * @return {@code this} (for chaining calls).
	 */
	public B setObjectDirectory(File objectDirectory) {
		this.objectDirectory = objectDirectory;
		return self();
	}

	/** @return the object directory; null if not set. */
	public File getObjectDirectory() {
		return objectDirectory;
	}

	/**
	 * Add an alternate object directory to the search list.
	 * <p>
	 * This setting handles one alternate directory at a time, and is provided
	 * to support {@code GIT_ALTERNATE_OBJECT_DIRECTORIES}.
	 *
	 * @param other
	 *            another objects directory to search after the standard one.
	 * @return {@code this} (for chaining calls).
	 */
	public B addAlternateObjectDirectory(File other) {
		if (other != null) {
			if (alternateObjectDirectories == null)
				alternateObjectDirectories = new LinkedList<>();
			alternateObjectDirectories.add(other);
		}
		return self();
	}

	/**
	 * Add alternate object directories to the search list.
	 * <p>
	 * This setting handles several alternate directories at once, and is
	 * provided to support {@code GIT_ALTERNATE_OBJECT_DIRECTORIES}.
	 *
	 * @param inList
	 *            other object directories to search after the standard one. The
	 *            collection's contents is copied to an internal list.
	 * @return {@code this} (for chaining calls).
	 */
	public B addAlternateObjectDirectories(Collection<File> inList) {
		if (inList != null) {
			for (File path : inList)
				addAlternateObjectDirectory(path);
		}
		return self();
	}

	/**
	 * Add alternate object directories to the search list.
	 * <p>
	 * This setting handles several alternate directories at once, and is
	 * provided to support {@code GIT_ALTERNATE_OBJECT_DIRECTORIES}.
	 *
	 * @param inList
	 *            other object directories to search after the standard one. The
	 *            array's contents is copied to an internal list.
	 * @return {@code this} (for chaining calls).
	 */
	public B addAlternateObjectDirectories(File[] inList) {
		if (inList != null) {
			for (File path : inList)
				addAlternateObjectDirectory(path);
		}
		return self();
	}

	/** @return ordered array of alternate directories; null if non were set. */
	public File[] getAlternateObjectDirectories() {
		final List<File> alts = alternateObjectDirectories;
		if (alts == null)
			return null;
		return alts.toArray(new File[alts.size()]);
	}

	/**
	 * Force the repository to be treated as bare (have no working directory).
	 * <p>
	 * If bare the working directory aspects of the repository won't be
	 * configured, and will not be accessible.
	 *
	 * @return {@code this} (for chaining calls).
	 */
	public B setBare() {
		setIndexFile(null);
		setWorkTree(null);
		bare = true;
		return self();
	}

	/** @return true if this repository was forced bare by {@link #setBare()}. */
	public boolean isBare() {
		return bare;
	}

	/**
	 * Require the repository to exist before it can be opened.
	 *
	 * @param mustExist
	 *            true if it must exist; false if it can be missing and created
	 *            after being built.
	 * @return {@code this} (for chaining calls).
	 */
	public B setMustExist(boolean mustExist) {
		this.mustExist = mustExist;
		return self();
	}

	/** @return true if the repository must exist before being opened. */
	public boolean isMustExist() {
		return mustExist;
	}

	/**
	 * Set the top level directory of the working files.
	 *
	 * @param workTree
	 *            {@code GIT_WORK_TREE}, the working directory of the checkout.
	 * @return {@code this} (for chaining calls).
	 */
	public B setWorkTree(File workTree) {
		this.workTree = workTree;
		return self();
	}

	/** @return the work tree directory, or null if not set. */
	public File getWorkTree() {
		return workTree;
	}

	/**
	 * Set the local index file that is caching checked out file status.
	 * <p>
	 * The location of the index file tracking the status information for each
	 * checked out file in {@code workTree}. This may be null to assume the
	 * default {@code gitDiir/index}.
	 *
	 * @param indexFile
	 *            {@code GIT_INDEX_FILE}, the index file location.
	 * @return {@code this} (for chaining calls).
	 */
	public B setIndexFile(File indexFile) {
		this.indexFile = indexFile;
		return self();
	}

	/** @return the index file location, or null if not set. */
	public File getIndexFile() {
		return indexFile;
	}

	/**
	 * Read standard Git environment variables and configure from those.
	 * <p>
	 * This method tries to read the standard Git environment variables, such as
	 * {@code GIT_DIR} and {@code GIT_WORK_TREE} to configure this builder
	 * instance. If an environment variable is set, it overrides the value
	 * already set in this builder.
	 *
	 * @return {@code this} (for chaining calls).
	 */
	public B readEnvironment() {
		return readEnvironment(SystemReader.getInstance());
	}

	/**
	 * Read standard Git environment variables and configure from those.
	 * <p>
	 * This method tries to read the standard Git environment variables, such as
	 * {@code GIT_DIR} and {@code GIT_WORK_TREE} to configure this builder
	 * instance. If a property is already set in the builder, the environment
	 * variable is not used.
	 *
	 * @param sr
	 *            the SystemReader abstraction to access the environment.
	 * @return {@code this} (for chaining calls).
	 */
	public B readEnvironment(SystemReader sr) {
		if (getGitDir() == null) {
			String val = sr.getenv(GIT_DIR_KEY);
			if (val != null)
				setGitDir(new File(val));
		}

		if (getObjectDirectory() == null) {
			String val = sr.getenv(GIT_OBJECT_DIRECTORY_KEY);
			if (val != null)
				setObjectDirectory(new File(val));
		}

		if (getAlternateObjectDirectories() == null) {
			String val = sr.getenv(GIT_ALTERNATE_OBJECT_DIRECTORIES_KEY);
			if (val != null) {
				for (String path : val.split(File.pathSeparator))
					addAlternateObjectDirectory(new File(path));
			}
		}

		if (getWorkTree() == null) {
			String val = sr.getenv(GIT_WORK_TREE_KEY);
			if (val != null)
				setWorkTree(new File(val));
		}

		if (getIndexFile() == null) {
			String val = sr.getenv(GIT_INDEX_FILE_KEY);
			if (val != null)
				setIndexFile(new File(val));
		}

		if (ceilingDirectories == null) {
			String val = sr.getenv(GIT_CEILING_DIRECTORIES_KEY);
			if (val != null) {
				for (String path : val.split(File.pathSeparator))
					addCeilingDirectory(new File(path));
			}
		}

		return self();
	}

	/**
	 * Add a ceiling directory to the search limit list.
	 * <p>
	 * This setting handles one ceiling directory at a time, and is provided to
	 * support {@code GIT_CEILING_DIRECTORIES}.
	 *
	 * @param root
	 *            a path to stop searching at; its parent will not be searched.
	 * @return {@code this} (for chaining calls).
	 */
	public B addCeilingDirectory(File root) {
		if (root != null) {
			if (ceilingDirectories == null)
				ceilingDirectories = new LinkedList<>();
			ceilingDirectories.add(root);
		}
		return self();
	}

	/**
	 * Add ceiling directories to the search list.
	 * <p>
	 * This setting handles several ceiling directories at once, and is provided
	 * to support {@code GIT_CEILING_DIRECTORIES}.
	 *
	 * @param inList
	 *            directory paths to stop searching at. The collection's
	 *            contents is copied to an internal list.
	 * @return {@code this} (for chaining calls).
	 */
	public B addCeilingDirectories(Collection<File> inList) {
		if (inList != null) {
			for (File path : inList)
				addCeilingDirectory(path);
		}
		return self();
	}

	/**
	 * Add ceiling directories to the search list.
	 * <p>
	 * This setting handles several ceiling directories at once, and is provided
	 * to support {@code GIT_CEILING_DIRECTORIES}.
	 *
	 * @param inList
	 *            directory paths to stop searching at. The array's contents is
	 *            copied to an internal list.
	 * @return {@code this} (for chaining calls).
	 */
	public B addCeilingDirectories(File[] inList) {
		if (inList != null) {
			for (File path : inList)
				addCeilingDirectory(path);
		}
		return self();
	}

	/**
	 * Configure {@code GIT_DIR} by searching up the file system.
	 * <p>
	 * Starts from the current working directory of the JVM and scans up through
	 * the directory tree until a Git repository is found. Success can be
	 * determined by checking for {@code getGitDir() != null}.
	 * <p>
	 * The search can be limited to specific spaces of the local filesystem by
	 * {@link #addCeilingDirectory(File)}, or inheriting the list through a
	 * prior call to {@link #readEnvironment()}.
	 *
	 * @return {@code this} (for chaining calls).
	 */
	public B findGitDir() {
		if (getGitDir() == null)
			findGitDir(new File("").getAbsoluteFile()); //$NON-NLS-1$
		return self();
	}

	/**
	 * Configure {@code GIT_DIR} by searching up the file system.
	 * <p>
	 * Starts from the supplied directory path and scans up through the parent
	 * directory tree until a Git repository is found. Success can be determined
	 * by checking for {@code getGitDir() != null}.
	 * <p>
	 * The search can be limited to specific spaces of the local filesystem by
	 * {@link #addCeilingDirectory(File)}, or inheriting the list through a
	 * prior call to {@link #readEnvironment()}.
	 *
	 * @param current
	 *            directory to begin searching in.
	 * @return {@code this} (for chaining calls).
	 */
	public B findGitDir(File current) {
		if (getGitDir() == null) {
			FS tryFS = safeFS();
			while (current != null) {
				File dir = new File(current, DOT_GIT);
				if (FileKey.isGitRepository(dir, tryFS)) {
					setGitDir(dir);
					break;
				} else if (dir.isFile()) {
					try {
						setGitDir(getSymRef(current, dir, tryFS));
						break;
					} catch (IOException ignored) {
						// Continue searching if gitdir ref isn't found
					}
				} else if (FileKey.isGitRepository(current, tryFS)) {
					setGitDir(current);
					break;
				}

				current = current.getParentFile();
				if (current != null && ceilingDirectories != null
						&& ceilingDirectories.contains(current))
					break;
			}
		}
		return self();
	}

	/**
	 * Guess and populate all parameters not already defined.
	 * <p>
	 * If an option was not set, the setup method will try to default the option
	 * based on other options. If insufficient information is available, an
	 * exception is thrown to the caller.
	 *
	 * @return {@code this}
	 * @throws IllegalArgumentException
	 *             insufficient parameters were set, or some parameters are
	 *             incompatible with one another.
	 * @throws IOException
	 *             the repository could not be accessed to configure the rest of
	 *             the builder's parameters.
	 */
	public B setup() throws IllegalArgumentException, IOException {
		requireGitDirOrWorkTree();
		setupGitDir();
		setupWorkTree();
		setupInternals();
		return self();
	}

	/**
	 * Create a repository matching the configuration in this builder.
	 * <p>
	 * If an option was not set, the build method will try to default the option
	 * based on other options. If insufficient information is available, an
	 * exception is thrown to the caller.
	 *
	 * @return a repository matching this configuration. The caller is
	 *         responsible to close the repository instance when it is no longer
	 *         needed.
	 * @throws IllegalArgumentException
	 *             insufficient parameters were set.
	 * @throws IOException
	 *             the repository could not be accessed to configure the rest of
	 *             the builder's parameters.
	 */
	@SuppressWarnings({ "unchecked", "resource" })
	public R build() throws IOException {
		R repo = (R) new FileRepository(setup());
		if (isMustExist() && !repo.getObjectDatabase().exists())
			throw new RepositoryNotFoundException(getGitDir());
		return repo;
	}

	/** Require either {@code gitDir} or {@code workTree} to be set. */
	protected void requireGitDirOrWorkTree() {
		if (getGitDir() == null && getWorkTree() == null)
			throw new IllegalArgumentException(
					JGitText.get().eitherGitDirOrWorkTreeRequired);
	}

	/**
	 * Perform standard gitDir initialization.
	 *
	 * @throws IOException
	 *             the repository could not be accessed
	 */
	protected void setupGitDir() throws IOException {
		// No gitDir? Try to assume its under the workTree or a ref to another
		// location
		if (getGitDir() == null && getWorkTree() != null) {
			File dotGit = new File(getWorkTree(), DOT_GIT);
			if (!dotGit.isFile())
				setGitDir(dotGit);
			else
				setGitDir(getSymRef(getWorkTree(), dotGit, safeFS()));
		}
	}

	/**
	 * Perform standard work-tree initialization.
	 * <p>
	 * This is a method typically invoked inside of {@link #setup()}, near the
	 * end after the repository has been identified and its configuration is
	 * available for inspection.
	 *
	 * @throws IOException
	 *             the repository configuration could not be read.
	 */
	protected void setupWorkTree() throws IOException {
		if (getFS() == null)
			setFS(FS.DETECTED);

		// If we aren't bare, we should have a work tree.
		//
		if (!isBare() && getWorkTree() == null)
			setWorkTree(guessWorkTreeOrFail());

		if (!isBare()) {
			// If after guessing we're still not bare, we must have
			// a metadata directory to hold the repository. Assume
			// its at the work tree.
			//
			if (getGitDir() == null)
				setGitDir(getWorkTree().getParentFile());
			if (getIndexFile() == null)
				setIndexFile(new File(getGitDir(), "index")); //$NON-NLS-1$
		}
	}

	/**
	 * Configure the internal implementation details of the repository.
	 *
	 * @throws IOException
	 *             the repository could not be accessed
	 */
	protected void setupInternals() throws IOException {
		if (getObjectDirectory() == null && getGitDir() != null)
			setObjectDirectory(safeFS().resolve(getGitDir(), "objects")); //$NON-NLS-1$
	}

	/**
	 * Get the cached repository configuration, loading if not yet available.
	 *
	 * @return the configuration of the repository.
	 * @throws IOException
	 *             the configuration is not available, or is badly formed.
	 */
	protected Config getConfig() throws IOException {
		if (config == null)
			config = loadConfig();
		return config;
	}

	/**
	 * Parse and load the repository specific configuration.
	 * <p>
	 * The default implementation reads {@code gitDir/config}, or returns an
	 * empty configuration if gitDir was not set.
	 *
	 * @return the repository's configuration.
	 * @throws IOException
	 *             the configuration is not available.
	 */
	protected Config loadConfig() throws IOException {
		if (getGitDir() != null) {
			// We only want the repository's configuration file, and not
			// the user file, as these parameters must be unique to this
			// repository and not inherited from other files.
			//
			File path = safeFS().resolve(getGitDir(), Constants.CONFIG);
			FileBasedConfig cfg = new FileBasedConfig(path, safeFS());
			try {
				cfg.load();
			} catch (ConfigInvalidException err) {
				throw new IllegalArgumentException(MessageFormat.format(
						JGitText.get().repositoryConfigFileInvalid, path
								.getAbsolutePath(), err.getMessage()));
			}
			return cfg;
		} else {
			return new Config();
		}
	}

	private File guessWorkTreeOrFail() throws IOException {
		final Config cfg = getConfig();

		// If set, core.worktree wins.
		//
		String path = cfg.getString(CONFIG_CORE_SECTION, null,
				CONFIG_KEY_WORKTREE);
		if (path != null)
			return safeFS().resolve(getGitDir(), path).getCanonicalFile();

		// If core.bare is set, honor its value. Assume workTree is
		// the parent directory of the repository.
		//
		if (cfg.getString(CONFIG_CORE_SECTION, null, CONFIG_KEY_BARE) != null) {
			if (cfg.getBoolean(CONFIG_CORE_SECTION, CONFIG_KEY_BARE, true)) {
				setBare();
				return null;
			}
			return getGitDir().getParentFile();
		}

		if (getGitDir().getName().equals(DOT_GIT)) {
			// No value for the "bare" flag, but gitDir is named ".git",
			// use the parent of the directory
			//
			return getGitDir().getParentFile();
		}

		// We have to assume we are bare.
		//
		setBare();
		return null;
	}

	/** @return the configured FS, or {@link FS#DETECTED}. */
	protected FS safeFS() {
		return getFS() != null ? getFS() : FS.DETECTED;
	}

	/** @return {@code this} */
	@SuppressWarnings("unchecked")
	protected final B self() {
		return (B) this;
	}
}