/*
 * 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.transport;

import static org.eclipse.jgit.lib.Constants.INFO_ALTERNATES;
import static org.eclipse.jgit.lib.Constants.LOCK_SUFFIX;
import static org.eclipse.jgit.lib.Constants.OBJECTS;

import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.OutputStream;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import org.eclipse.jgit.errors.NotSupportedException;
import org.eclipse.jgit.errors.TransportException;
import org.eclipse.jgit.internal.JGitText;
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.lib.Ref.Storage;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.lib.SymbolicRef;

/**
 * Transport over the non-Git aware SFTP (SSH based FTP) protocol.
 * <p>
 * The SFTP transport does not require any specialized Git support on the remote
 * (server side) repository. Object files are retrieved directly through secure
 * shell's FTP protocol, making it possible to copy objects from a remote
 * repository that is available over SSH, but whose remote host does not have
 * Git installed.
 * <p>
 * Unlike the HTTP variant (see
 * {@link org.eclipse.jgit.transport.TransportHttp}) we rely upon being able to
 * list files in directories, as the SFTP protocol supports this function. By
 * listing files through SFTP we can avoid needing to have current
 * <code>objects/info/packs</code> or <code>info/refs</code> files on the remote
 * repository and access the data directly, much as Git itself would.
 * <p>
 * Concurrent pushing over this transport is not supported. Multiple concurrent
 * push operations may cause confusion in the repository state.
 *
 * @see WalkFetchConnection
 */
public class TransportSftp extends SshTransport implements WalkTransport {
	static final TransportProtocol PROTO_SFTP = new TransportProtocol() {
		@Override
		public String getName() {
			return JGitText.get().transportProtoSFTP;
		}

		@Override
		public Set<String> getSchemes() {
			return Collections.singleton("sftp"); //$NON-NLS-1$
		}

		@Override
		public Set<URIishField> getRequiredFields() {
			return Collections.unmodifiableSet(EnumSet.of(URIishField.HOST,
					URIishField.PATH));
		}

		@Override
		public Set<URIishField> getOptionalFields() {
			return Collections.unmodifiableSet(EnumSet.of(URIishField.USER,
					URIishField.PASS, URIishField.PORT));
		}

		@Override
		public int getDefaultPort() {
			return 22;
		}

		@Override
		public Transport open(URIish uri, Repository local, String remoteName)
				throws NotSupportedException {
			return new TransportSftp(local, uri);
		}
	};

	TransportSftp(Repository local, URIish uri) {
		super(local, uri);
	}

	/** {@inheritDoc} */
	@Override
	public FetchConnection openFetch() throws TransportException {
		final SftpObjectDB c = new SftpObjectDB(uri.getPath());
		final WalkFetchConnection r = new WalkFetchConnection(this, c);
		r.available(c.readAdvertisedRefs());
		return r;
	}

	/** {@inheritDoc} */
	@Override
	public PushConnection openPush() throws TransportException {
		final SftpObjectDB c = new SftpObjectDB(uri.getPath());
		final WalkPushConnection r = new WalkPushConnection(this, c);
		r.available(c.readAdvertisedRefs());
		return r;
	}

	FtpChannel newSftp() throws IOException {
		FtpChannel channel = getSession().getFtpChannel();
		channel.connect(getTimeout(), TimeUnit.SECONDS);
		return channel;
	}

	class SftpObjectDB extends WalkRemoteObjectDatabase {
		private final String objectsPath;

		private FtpChannel ftp;

		SftpObjectDB(String path) throws TransportException {
			if (path.startsWith("/~")) //$NON-NLS-1$
				path = path.substring(1);
			if (path.startsWith("~/")) //$NON-NLS-1$
				path = path.substring(2);
			try {
				ftp = newSftp();
				ftp.cd(path);
				ftp.cd(OBJECTS);
				objectsPath = ftp.pwd();
			} catch (FtpChannel.FtpException f) {
				throw new TransportException(MessageFormat.format(
						JGitText.get().cannotEnterObjectsPath, path,
						f.getMessage()), f);
			} catch (IOException ioe) {
				close();
				throw new TransportException(uri, ioe.getMessage(), ioe);
			}
		}

		SftpObjectDB(SftpObjectDB parent, String p)
				throws TransportException {
			try {
				ftp = newSftp();
				ftp.cd(parent.objectsPath);
				ftp.cd(p);
				objectsPath = ftp.pwd();
			} catch (FtpChannel.FtpException f) {
				throw new TransportException(MessageFormat.format(
						JGitText.get().cannotEnterPathFromParent, p,
						parent.objectsPath, f.getMessage()), f);
			} catch (IOException ioe) {
				close();
				throw new TransportException(uri, ioe.getMessage(), ioe);
			}
		}

		@Override
		URIish getURI() {
			return uri.setPath(objectsPath);
		}

		@Override
		Collection<WalkRemoteObjectDatabase> getAlternates() throws IOException {
			try {
				return readAlternates(INFO_ALTERNATES);
			} catch (FileNotFoundException err) {
				return null;
			}
		}

		@Override
		WalkRemoteObjectDatabase openAlternate(String location)
				throws IOException {
			return new SftpObjectDB(this, location);
		}

		@Override
		Collection<String> getPackNames() throws IOException {
			final List<String> packs = new ArrayList<>();
			try {
				Collection<FtpChannel.DirEntry> list = ftp.ls("pack"); //$NON-NLS-1$
				Set<String> files = list.stream()
						.map(FtpChannel.DirEntry::getFilename)
						.collect(Collectors.toSet());
				HashMap<String, Long> mtimes = new HashMap<>();

				for (FtpChannel.DirEntry ent : list) {
					String n = ent.getFilename();
					if (!n.startsWith("pack-") || !n.endsWith(".pack")) { //$NON-NLS-1$ //$NON-NLS-2$
						continue;
					}
					String in = n.substring(0, n.length() - 5) + ".idx"; //$NON-NLS-1$
					if (!files.contains(in)) {
						continue;
					}
					mtimes.put(n, Long.valueOf(ent.getModifiedTime()));
					packs.add(n);
				}

				Collections.sort(packs,
						(o1, o2) -> mtimes.get(o2).compareTo(mtimes.get(o1)));
			} catch (FtpChannel.FtpException f) {
				throw new TransportException(
						MessageFormat.format(JGitText.get().cannotListPackPath,
								objectsPath, f.getMessage()),
						f);
			}
			return packs;
		}

		@Override
		FileStream open(String path) throws IOException {
			try {
				return new FileStream(ftp.get(path));
			} catch (FtpChannel.FtpException f) {
				if (f.getStatus() == FtpChannel.FtpException.NO_SUCH_FILE) {
					throw new FileNotFoundException(path);
				}
				throw new TransportException(MessageFormat.format(
						JGitText.get().cannotGetObjectsPath, objectsPath, path,
						f.getMessage()), f);
			}
		}

		@Override
		void deleteFile(String path) throws IOException {
			try {
				ftp.delete(path);
			} catch (FtpChannel.FtpException f) {
				throw new TransportException(MessageFormat.format(
						JGitText.get().cannotDeleteObjectsPath, objectsPath,
						path, f.getMessage()), f);
			}

			// Prune any now empty directories.
			//
			String dir = path;
			int s = dir.lastIndexOf('/');
			while (s > 0) {
				try {
					dir = dir.substring(0, s);
					ftp.rmdir(dir);
					s = dir.lastIndexOf('/');
				} catch (IOException je) {
					// If we cannot delete it, leave it alone. It may have
					// entries still in it, or maybe we lack write access on
					// the parent. Either way it isn't a fatal error.
					//
					break;
				}
			}
		}

		@Override
		OutputStream writeFile(String path, ProgressMonitor monitor,
				String monitorTask) throws IOException {
			Throwable err = null;
			try {
				return ftp.put(path);
			} catch (FileNotFoundException e) {
				mkdir_p(path);
			} catch (FtpChannel.FtpException je) {
				if (je.getStatus() == FtpChannel.FtpException.NO_SUCH_FILE) {
					mkdir_p(path);
				} else {
					err = je;
				}
			}
			if (err == null) {
				try {
					return ftp.put(path);
				} catch (IOException e) {
					err = e;
				}
			}
			throw new TransportException(
					MessageFormat.format(JGitText.get().cannotWriteObjectsPath,
							objectsPath, path, err.getMessage()),
					err);
		}

		@Override
		void writeFile(String path, byte[] data) throws IOException {
			final String lock = path + LOCK_SUFFIX;
			try {
				super.writeFile(lock, data);
				try {
					ftp.rename(lock, path);
				} catch (IOException e) {
					throw new TransportException(MessageFormat.format(
							JGitText.get().cannotWriteObjectsPath, objectsPath,
							path, e.getMessage()), e);
				}
			} catch (IOException err) {
				try {
					ftp.rm(lock);
				} catch (IOException e) {
					// Ignore deletion failure, we are already
					// failing anyway.
				}
				throw err;
			}
		}

		private void mkdir_p(String path) throws IOException {
			final int s = path.lastIndexOf('/');
			if (s <= 0)
				return;

			path = path.substring(0, s);
			Throwable err = null;
			try {
				ftp.mkdir(path);
				return;
			} catch (FileNotFoundException f) {
				mkdir_p(path);
			} catch (FtpChannel.FtpException je) {
				if (je.getStatus() == FtpChannel.FtpException.NO_SUCH_FILE) {
					mkdir_p(path);
				} else {
					err = je;
				}
			}
			if (err == null) {
				try {
					ftp.mkdir(path);
					return;
				} catch (IOException e) {
					err = e;
				}
			}
			throw new TransportException(MessageFormat.format(
						JGitText.get().cannotMkdirObjectPath, objectsPath, path,
					err.getMessage()), err);
		}

		Map<String, Ref> readAdvertisedRefs() throws TransportException {
			final TreeMap<String, Ref> avail = new TreeMap<>();
			readPackedRefs(avail);
			readRef(avail, ROOT_DIR + Constants.HEAD, Constants.HEAD);
			readLooseRefs(avail, ROOT_DIR + "refs", "refs/"); //$NON-NLS-1$ //$NON-NLS-2$
			return avail;
		}

		private void readLooseRefs(TreeMap<String, Ref> avail, String dir,
				String prefix) throws TransportException {
			final Collection<FtpChannel.DirEntry> list;
			try {
				list = ftp.ls(dir);
			} catch (IOException e) {
				throw new TransportException(MessageFormat.format(
						JGitText.get().cannotListObjectsPath, objectsPath, dir,
						e.getMessage()), e);
			}

			for (FtpChannel.DirEntry ent : list) {
				String n = ent.getFilename();
				if (".".equals(n) || "..".equals(n)) //$NON-NLS-1$ //$NON-NLS-2$
					continue;

				String nPath = dir + "/" + n; //$NON-NLS-1$
				if (ent.isDirectory()) {
					readLooseRefs(avail, nPath, prefix + n + "/"); //$NON-NLS-1$
				} else {
					readRef(avail, nPath, prefix + n);
				}
			}
		}

		private Ref readRef(TreeMap<String, Ref> avail, String path,
				String name) throws TransportException {
			final String line;
			try (BufferedReader br = openReader(path)) {
				line = br.readLine();
			} catch (FileNotFoundException noRef) {
				return null;
			} catch (IOException err) {
				throw new TransportException(MessageFormat.format(
						JGitText.get().cannotReadObjectsPath, objectsPath, path,
						err.getMessage()), err);
			}

			if (line == null) {
				throw new TransportException(
						MessageFormat.format(JGitText.get().emptyRef, name));
			}
			if (line.startsWith("ref: ")) { //$NON-NLS-1$
				final String target = line.substring("ref: ".length()); //$NON-NLS-1$
				Ref r = avail.get(target);
				if (r == null)
					r = readRef(avail, ROOT_DIR + target, target);
				if (r == null)
					r = new ObjectIdRef.Unpeeled(Ref.Storage.NEW, target, null);
				r = new SymbolicRef(name, r);
				avail.put(r.getName(), r);
				return r;
			}

			if (ObjectId.isId(line)) {
				final Ref r = new ObjectIdRef.Unpeeled(loose(avail.get(name)),
						name, ObjectId.fromString(line));
				avail.put(r.getName(), r);
				return r;
			}

			throw new TransportException(
					MessageFormat.format(JGitText.get().badRef, name, line));
		}

		private Storage loose(Ref r) {
			if (r != null && r.getStorage() == Storage.PACKED) {
				return Storage.LOOSE_PACKED;
			}
			return Storage.LOOSE;
		}

		@Override
		void close() {
			if (ftp != null) {
				try {
					if (ftp.isConnected()) {
						ftp.disconnect();
					}
				} finally {
					ftp = null;
				}
			}
		}
	}
}
