/*
 * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org>
 * 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.transport;

import static java.nio.charset.StandardCharsets.UTF_8;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Map;

import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.internal.storage.file.RefDirectory;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectIdRef;
import org.eclipse.jgit.lib.ProgressMonitor;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.util.IO;

/**
 * Transfers object data through a dumb transport.
 * <p>
 * Implementations are responsible for resolving path names relative to the
 * <code>objects/</code> subdirectory of a single remote Git repository or
 * naked object database and make the content available as a Java input stream
 * for reading during fetch. The actual object traversal logic to determine the
 * names of files to retrieve is handled through the generic, protocol
 * independent {@link WalkFetchConnection}.
 */
abstract class WalkRemoteObjectDatabase {
	static final String ROOT_DIR = "../"; //$NON-NLS-1$

	static final String INFO_PACKS = "info/packs"; //$NON-NLS-1$

	static final String INFO_ALTERNATES = "info/alternates"; //$NON-NLS-1$

	static final String INFO_HTTP_ALTERNATES = "info/http-alternates"; //$NON-NLS-1$

	static final String INFO_REFS = ROOT_DIR + Constants.INFO_REFS;

	abstract URIish getURI();

	/**
	 * Obtain the list of available packs (if any).
	 * <p>
	 * Pack names should be the file name in the packs directory, that is
	 * <code>pack-035760ab452d6eebd123add421f253ce7682355a.pack</code>. Index
	 * names should not be included in the returned collection.
	 *
	 * @return list of pack names; null or empty list if none are available.
	 * @throws IOException
	 *             The connection is unable to read the remote repository's list
	 *             of available pack files.
	 */
	abstract Collection<String> getPackNames() throws IOException;

	/**
	 * Obtain alternate connections to alternate object databases (if any).
	 * <p>
	 * Alternates are typically read from the file {@link #INFO_ALTERNATES} or
	 * {@link #INFO_HTTP_ALTERNATES}. The content of each line must be resolved
	 * by the implementation and a new database reference should be returned to
	 * represent the additional location.
	 * <p>
	 * Alternates may reuse the same network connection handle, however the
	 * fetch connection will {@link #close()} each created alternate.
	 *
	 * @return list of additional object databases the caller could fetch from;
	 *         null or empty list if none are configured.
	 * @throws IOException
	 *             The connection is unable to read the remote repository's list
	 *             of configured alternates.
	 */
	abstract Collection<WalkRemoteObjectDatabase> getAlternates()
			throws IOException;

	/**
	 * Open a single file for reading.
	 * <p>
	 * Implementors should make every attempt possible to ensure
	 * {@link FileNotFoundException} is used when the remote object does not
	 * exist. However when fetching over HTTP some misconfigured servers may
	 * generate a 200 OK status message (rather than a 404 Not Found) with an
	 * HTML formatted message explaining the requested resource does not exist.
	 * Callers such as {@link WalkFetchConnection} are prepared to handle this
	 * by validating the content received, and assuming content that fails to
	 * match its hash is an incorrectly phrased FileNotFoundException.
	 * <p>
	 * This method is recommended for already compressed files like loose objects
	 * and pack files. For text files, see {@link #openReader(String)}.
	 *
	 * @param path
	 *            location of the file to read, relative to this objects
	 *            directory (e.g.
	 *            <code>cb/95df6ab7ae9e57571511ef451cf33767c26dd2</code> or
	 *            <code>pack/pack-035760ab452d6eebd123add421f253ce7682355a.pack</code>).
	 * @return a stream to read from the file. Never null.
	 * @throws FileNotFoundException
	 *             the requested file does not exist at the given location.
	 * @throws IOException
	 *             The connection is unable to read the remote's file, and the
	 *             failure occurred prior to being able to determine if the file
	 *             exists, or after it was determined to exist but before the
	 *             stream could be created.
	 */
	abstract FileStream open(String path) throws FileNotFoundException,
			IOException;

	/**
	 * Create a new connection for a discovered alternate object database
	 * <p>
	 * This method is typically called by {@link #readAlternates(String)} when
	 * subclasses us the generic alternate parsing logic for their
	 * implementation of {@link #getAlternates()}.
	 *
	 * @param location
	 *            the location of the new alternate, relative to the current
	 *            object database.
	 * @return a new database connection that can read from the specified
	 *         alternate.
	 * @throws IOException
	 *             The database connection cannot be established with the
	 *             alternate, such as if the alternate location does not
	 *             actually exist and the connection's constructor attempts to
	 *             verify that.
	 */
	abstract WalkRemoteObjectDatabase openAlternate(String location)
			throws IOException;

	/**
	 * Close any resources used by this connection.
	 * <p>
	 * If the remote repository is contacted by a network socket this method
	 * must close that network socket, disconnecting the two peers. If the
	 * remote repository is actually local (same system) this method must close
	 * any open file handles used to read the "remote" repository.
	 */
	abstract void close();

	/**
	 * Delete a file from the object database.
	 * <p>
	 * Path may start with <code>../</code> to request deletion of a file that
	 * resides in the repository itself.
	 * <p>
	 * When possible empty directories must be removed, up to but not including
	 * the current object database directory itself.
	 * <p>
	 * This method does not support deletion of directories.
	 *
	 * @param path
	 *            name of the item to be removed, relative to the current object
	 *            database.
	 * @throws IOException
	 *             deletion is not supported, or deletion failed.
	 */
	void deleteFile(String path) throws IOException {
		throw new IOException(MessageFormat.format(JGitText.get().deletingNotSupported, path));
	}

	/**
	 * Open a remote file for writing.
	 * <p>
	 * Path may start with <code>../</code> to request writing of a file that
	 * resides in the repository itself.
	 * <p>
	 * The requested path may or may not exist. If the path already exists as a
	 * file the file should be truncated and completely replaced.
	 * <p>
	 * This method creates any missing parent directories, if necessary.
	 *
	 * @param path
	 *            name of the file to write, relative to the current object
	 *            database.
	 * @return stream to write into this file. Caller must close the stream to
	 *         complete the write request. The stream is not buffered and each
	 *         write may cause a network request/response so callers should
	 *         buffer to smooth out small writes.
	 * @param monitor
	 *            (optional) progress monitor to post write completion to during
	 *            the stream's close method.
	 * @param monitorTask
	 *            (optional) task name to display during the close method.
	 * @throws IOException
	 *             writing is not supported, or attempting to write the file
	 *             failed, possibly due to permissions or remote disk full, etc.
	 */
	OutputStream writeFile(final String path, final ProgressMonitor monitor,
			final String monitorTask) throws IOException {
		throw new IOException(MessageFormat.format(JGitText.get().writingNotSupported, path));
	}

	/**
	 * Atomically write a remote file.
	 * <p>
	 * This method attempts to perform as atomic of an update as it can,
	 * reducing (or eliminating) the time that clients might be able to see
	 * partial file content. This method is not suitable for very large
	 * transfers as the complete content must be passed as an argument.
	 * <p>
	 * Path may start with <code>../</code> to request writing of a file that
	 * resides in the repository itself.
	 * <p>
	 * The requested path may or may not exist. If the path already exists as a
	 * file the file should be truncated and completely replaced.
	 * <p>
	 * This method creates any missing parent directories, if necessary.
	 *
	 * @param path
	 *            name of the file to write, relative to the current object
	 *            database.
	 * @param data
	 *            complete new content of the file.
	 * @throws IOException
	 *             writing is not supported, or attempting to write the file
	 *             failed, possibly due to permissions or remote disk full, etc.
	 */
	void writeFile(String path, byte[] data) throws IOException {
		try (OutputStream os = writeFile(path, null, null)) {
			os.write(data);
		}
	}

	/**
	 * Delete a loose ref from the remote repository.
	 *
	 * @param name
	 *            name of the ref within the ref space, for example
	 *            <code>refs/heads/pu</code>.
	 * @throws IOException
	 *             deletion is not supported, or deletion failed.
	 */
	void deleteRef(String name) throws IOException {
		deleteFile(ROOT_DIR + name);
	}

	/**
	 * Delete a reflog from the remote repository.
	 *
	 * @param name
	 *            name of the ref within the ref space, for example
	 *            <code>refs/heads/pu</code>.
	 * @throws IOException
	 *             deletion is not supported, or deletion failed.
	 */
	void deleteRefLog(String name) throws IOException {
		deleteFile(ROOT_DIR + Constants.LOGS + "/" + name); //$NON-NLS-1$
	}

	/**
	 * Overwrite (or create) a loose ref in the remote repository.
	 * <p>
	 * This method creates any missing parent directories, if necessary.
	 *
	 * @param name
	 *            name of the ref within the ref space, for example
	 *            <code>refs/heads/pu</code>.
	 * @param value
	 *            new value to store in this ref. Must not be null.
	 * @throws IOException
	 *             writing is not supported, or attempting to write the file
	 *             failed, possibly due to permissions or remote disk full, etc.
	 */
	void writeRef(String name, ObjectId value) throws IOException {
		final ByteArrayOutputStream b;

		b = new ByteArrayOutputStream(Constants.OBJECT_ID_STRING_LENGTH + 1);
		value.copyTo(b);
		b.write('\n');

		writeFile(ROOT_DIR + name, b.toByteArray());
	}

	/**
	 * Rebuild the {@link #INFO_PACKS} for dumb transport clients.
	 * <p>
	 * This method rebuilds the contents of the {@link #INFO_PACKS} file to
	 * match the passed list of pack names.
	 *
	 * @param packNames
	 *            names of available pack files, in the order they should appear
	 *            in the file. Valid pack name strings are of the form
	 *            <code>pack-035760ab452d6eebd123add421f253ce7682355a.pack</code>.
	 * @throws IOException
	 *             writing is not supported, or attempting to write the file
	 *             failed, possibly due to permissions or remote disk full, etc.
	 */
	void writeInfoPacks(Collection<String> packNames) throws IOException {
		final StringBuilder w = new StringBuilder();
		for (String n : packNames) {
			w.append("P "); //$NON-NLS-1$
			w.append(n);
			w.append('\n');
		}
		writeFile(INFO_PACKS, Constants.encodeASCII(w.toString()));
	}

	/**
	 * Open a buffered reader around a file.
	 * <p>
	 * This method is suitable for for reading line-oriented resources like
	 * <code>info/packs</code>, <code>info/refs</code>, and the alternates list.
	 *
	 * @return a stream to read from the file. Never null.
	 * @param path
	 *            location of the file to read, relative to this objects
	 *            directory (e.g. <code>info/packs</code>).
	 * @throws FileNotFoundException
	 *             the requested file does not exist at the given location.
	 * @throws IOException
	 *             The connection is unable to read the remote's file, and the
	 *             failure occurred prior to being able to determine if the file
	 *             exists, or after it was determined to exist but before the
	 *             stream could be created.
	 */
	BufferedReader openReader(String path) throws IOException {
		final InputStream is = open(path).in;
		return new BufferedReader(new InputStreamReader(is, UTF_8));
	}

	/**
	 * Read a standard Git alternates file to discover other object databases.
	 * <p>
	 * This method is suitable for reading the standard formats of the
	 * alternates file, such as found in <code>objects/info/alternates</code>
	 * or <code>objects/info/http-alternates</code> within a Git repository.
	 * <p>
	 * Alternates appear one per line, with paths expressed relative to this
	 * object database.
	 *
	 * @param listPath
	 *            location of the alternate file to read, relative to this
	 *            object database (e.g. <code>info/alternates</code>).
	 * @return the list of discovered alternates. Empty list if the file exists,
	 *         but no entries were discovered.
	 * @throws FileNotFoundException
	 *             the requested file does not exist at the given location.
	 * @throws IOException
	 *             The connection is unable to read the remote's file, and the
	 *             failure occurred prior to being able to determine if the file
	 *             exists, or after it was determined to exist but before the
	 *             stream could be created.
	 */
	Collection<WalkRemoteObjectDatabase> readAlternates(final String listPath)
			throws IOException {
		try (BufferedReader br = openReader(listPath)) {
			final Collection<WalkRemoteObjectDatabase> alts = new ArrayList<>();
			for (;;) {
				String line = br.readLine();
				if (line == null)
					break;
				if (!line.endsWith("/")) //$NON-NLS-1$
					line += "/"; //$NON-NLS-1$
				alts.add(openAlternate(line));
			}
			return alts;
		}
	}

	/**
	 * Read a standard Git packed-refs file to discover known references.
	 *
	 * @param avail
	 *            return collection of references. Any existing entries will be
	 *            replaced if they are found in the packed-refs file.
	 * @throws org.eclipse.jgit.errors.TransportException
	 *             an error occurred reading from the packed refs file.
	 */
	protected void readPackedRefs(Map<String, Ref> avail)
			throws TransportException {
		try (BufferedReader br = openReader(ROOT_DIR + Constants.PACKED_REFS)) {
			readPackedRefsImpl(avail, br);
		} catch (FileNotFoundException notPacked) {
			// Perhaps it wasn't worthwhile, or is just an older repository.
		} catch (IOException e) {
			throw new TransportException(getURI(), JGitText.get().errorInPackedRefs, e);
		}
	}

	private void readPackedRefsImpl(final Map<String, Ref> avail,
			final BufferedReader br) throws IOException {
		Ref last = null;
		boolean peeled = false;
		for (;;) {
			String line = br.readLine();
			if (line == null)
				break;
			if (line.charAt(0) == '#') {
				if (line.startsWith(RefDirectory.PACKED_REFS_HEADER)) {
					line = line.substring(RefDirectory.PACKED_REFS_HEADER.length());
					peeled = line.contains(RefDirectory.PACKED_REFS_PEELED);
				}
				continue;
			}
			if (line.charAt(0) == '^') {
				if (last == null)
					throw new TransportException(JGitText.get().peeledLineBeforeRef);
				final ObjectId id = ObjectId.fromString(line.substring(1));
				last = new ObjectIdRef.PeeledTag(Ref.Storage.PACKED, last
						.getName(), last.getObjectId(), id);
				avail.put(last.getName(), last);
				continue;
			}

			final int sp = line.indexOf(' ');
			if (sp < 0)
				throw new TransportException(MessageFormat.format(JGitText.get().unrecognizedRef, line));
			final ObjectId id = ObjectId.fromString(line.substring(0, sp));
			final String name = line.substring(sp + 1);
			if (peeled)
				last = new ObjectIdRef.PeeledNonTag(Ref.Storage.PACKED, name, id);
			else
				last = new ObjectIdRef.Unpeeled(Ref.Storage.PACKED, name, id);
			avail.put(last.getName(), last);
		}
	}

	static final class FileStream {
		final InputStream in;

		final long length;

		/**
		 * Create a new stream of unknown length.
		 *
		 * @param i
		 *            stream containing the file data. This stream will be
		 *            closed by the caller when reading is complete.
		 */
		FileStream(InputStream i) {
			in = i;
			length = -1;
		}

		/**
		 * Create a new stream of known length.
		 *
		 * @param i
		 *            stream containing the file data. This stream will be
		 *            closed by the caller when reading is complete.
		 * @param n
		 *            total number of bytes available for reading through
		 *            <code>i</code>.
		 */
		FileStream(InputStream i, long n) {
			in = i;
			length = n;
		}

		byte[] toArray() throws IOException {
			try {
				if (length >= 0) {
					final byte[] r = new byte[(int) length];
					IO.readFully(in, r, 0, r.length);
					return r;
				}

				final ByteArrayOutputStream r = new ByteArrayOutputStream();
				final byte[] buf = new byte[2048];
				int n;
				while ((n = in.read(buf)) >= 0)
					r.write(buf, 0, n);
				return r.toByteArray();
			} finally {
				in.close();
			}
		}
	}
}
