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

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
import static org.eclipse.jgit.lib.Constants.OBJ_COMMIT;
import static org.eclipse.jgit.lib.FileMode.TYPE_FILE;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;

import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheEditor;
import org.eclipse.jgit.dircache.DirCacheEditor.PathEdit;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.FileMode;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectInserter;
import org.eclipse.jgit.lib.ObjectLoader;
import org.eclipse.jgit.lib.ObjectReader;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.treewalk.TreeWalk;
import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
import org.eclipse.jgit.treewalk.filter.PathFilter;
import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
import org.eclipse.jgit.treewalk.filter.TreeFilter;

/**
 * Storage for recorded push certificates.
 * <p>
 * Push certificates are stored in a special ref {@code refs/meta/push-certs}.
 * The filenames in the tree are ref names followed by the special suffix
 * <code>@{cert}</code>, and the contents are the latest push cert affecting
 * that ref. The special suffix allows storing certificates for both refs/foo
 * and refs/foo/bar in case those both existed at some point.
 *
 * @since 4.1
 */
public class PushCertificateStore implements AutoCloseable {
	/** Ref name storing push certificates. */
	static final String REF_NAME =
			Constants.R_REFS + "meta/push-certs"; //$NON-NLS-1$

	private static class PendingCert {
		PushCertificate cert;
		PersonIdent ident;
		Collection<ReceiveCommand> matching;

		PendingCert(PushCertificate cert, PersonIdent ident,
				Collection<ReceiveCommand> matching) {
			this.cert = cert;
			this.ident = ident;
			this.matching = matching;
		}
	}

	private final Repository db;
	private final List<PendingCert> pending;
	ObjectReader reader;
	RevCommit commit;

	/**
	 * Create a new store backed by the given repository.
	 *
	 * @param db
	 *            the repository.
	 */
	public PushCertificateStore(Repository db) {
		this.db = db;
		pending = new ArrayList<>();
	}

	/**
	 * {@inheritDoc}
	 * <p>
	 * Close resources opened by this store.
	 * <p>
	 * If {@link #get(String)} was called, closes the cached object reader
	 * created by that method. Does not close the underlying repository.
	 */
	@Override
	public void close() {
		if (reader != null) {
			reader.close();
			reader = null;
			commit = null;
		}
	}

	/**
	 * Get latest push certificate associated with a ref.
	 * <p>
	 * Lazily opens {@code refs/meta/push-certs} and reads from the repository as
	 * necessary. The state is cached between calls to {@code get}; to reread the,
	 * call {@link #close()} first.
	 *
	 * @param refName
	 *            the ref name to get the certificate for.
	 * @return last certificate affecting the ref, or null if no cert was recorded
	 *         for the last update to this ref.
	 * @throws java.io.IOException
	 *             if a problem occurred reading the repository.
	 */
	public PushCertificate get(String refName) throws IOException {
		if (reader == null) {
			load();
		}
		try (TreeWalk tw = newTreeWalk(refName)) {
			return read(tw);
		}
	}

	/**
	 * Iterate over all push certificates affecting a ref.
	 * <p>
	 * Only includes push certificates actually stored in the tree; see class
	 * Javadoc for conditions where this might not include all push certs ever
	 * seen for this ref.
	 * <p>
	 * The returned iterable may be iterated multiple times, and push certs will
	 * be re-read from the current state of the store on each call to {@link
	 * Iterable#iterator()}. However, method calls on the returned iterator may
	 * fail if {@code save} or {@code close} is called on the enclosing store
	 * during iteration.
	 *
	 * @param refName
	 *            the ref name to get certificates for.
	 * @return iterable over certificates; must be fully iterated in order to
	 *         close resources.
	 */
	public Iterable<PushCertificate> getAll(String refName) {
		return new Iterable<PushCertificate>() {
			@Override
			public Iterator<PushCertificate> iterator() {
				return new Iterator<PushCertificate>() {
					private final String path = pathName(refName);
					private PushCertificate next;

					private RevWalk rw;
					{
						try {
							if (reader == null) {
								load();
							}
							if (commit != null) {
								rw = new RevWalk(reader);
								rw.setTreeFilter(AndTreeFilter.create(
										PathFilterGroup.create(
											Collections.singleton(PathFilter.create(path))),
										TreeFilter.ANY_DIFF));
								rw.setRewriteParents(false);
								rw.markStart(rw.parseCommit(commit));
							} else {
								rw = null;
							}
						} catch (IOException e) {
							throw new RuntimeException(e);
						}
					}

					@Override
					public boolean hasNext() {
						try {
							if (next == null) {
								if (rw == null) {
									return false;
								}
								try {
									RevCommit c = rw.next();
									if (c != null) {
										try (TreeWalk tw = TreeWalk.forPath(
												rw.getObjectReader(), path, c.getTree())) {
											next = read(tw);
										}
									} else {
										next = null;
									}
								} catch (IOException e) {
									throw new RuntimeException(e);
								}
							}
							return next != null;
						} finally {
							if (next == null && rw != null) {
								rw.close();
								rw = null;
							}
						}
					}

					@Override
					public PushCertificate next() {
						hasNext();
						PushCertificate n = next;
						if (n == null) {
							throw new NoSuchElementException();
						}
						next = null;
						return n;
					}

					@Override
					public void remove() {
						throw new UnsupportedOperationException();
					}
				};
			}
		};
	}

	void load() throws IOException {
		close();
		reader = db.newObjectReader();
		Ref ref = db.getRefDatabase().exactRef(REF_NAME);
		if (ref == null) {
			// No ref, same as empty.
			return;
		}
		try (RevWalk rw = new RevWalk(reader)) {
			commit = rw.parseCommit(ref.getObjectId());
		}
	}

	static PushCertificate read(TreeWalk tw) throws IOException {
		if (tw == null || (tw.getRawMode(0) & TYPE_FILE) != TYPE_FILE) {
			return null;
		}
		ObjectLoader loader =
				tw.getObjectReader().open(tw.getObjectId(0), OBJ_BLOB);
		try (InputStream in = loader.openStream();
				Reader r = new BufferedReader(
						new InputStreamReader(in, UTF_8))) {
			return PushCertificateParser.fromReader(r);
		}
	}

	/**
	 * Put a certificate to be saved to the store.
	 * <p>
	 * Writes the contents of this certificate for each ref mentioned. It is up
	 * to the caller to ensure this certificate accurately represents the state
	 * of the ref.
	 * <p>
	 * Pending certificates added to this method are not returned by
	 * {@link #get(String)} and {@link #getAll(String)} until after calling
	 * {@link #save()}.
	 *
	 * @param cert
	 *            certificate to store.
	 * @param ident
	 *            identity for the commit that stores this certificate. Pending
	 *            certificates are sorted by identity timestamp during
	 *            {@link #save()}.
	 */
	public void put(PushCertificate cert, PersonIdent ident) {
		put(cert, ident, null);
	}

	/**
	 * Put a certificate to be saved to the store, matching a set of commands.
	 * <p>
	 * Like {@link #put(PushCertificate, PersonIdent)}, except a value is only
	 * stored for a push certificate if there is a corresponding command in the
	 * list that exactly matches the old/new values mentioned in the push
	 * certificate.
	 * <p>
	 * Pending certificates added to this method are not returned by
	 * {@link #get(String)} and {@link #getAll(String)} until after calling
	 * {@link #save()}.
	 *
	 * @param cert
	 *            certificate to store.
	 * @param ident
	 *            identity for the commit that stores this certificate. Pending
	 *            certificates are sorted by identity timestamp during
	 *            {@link #save()}.
	 * @param matching
	 *            only store certs for the refs listed in this list whose values
	 *            match the commands in the cert.
	 */
	public void put(PushCertificate cert, PersonIdent ident,
			Collection<ReceiveCommand> matching) {
		pending.add(new PendingCert(cert, ident, matching));
	}

	/**
	 * Save pending certificates to the store.
	 * <p>
	 * One commit is created per certificate added with
	 * {@link #put(PushCertificate, PersonIdent)}, in order of identity
	 * timestamps, and a single ref update is performed.
	 * <p>
	 * The pending list is cleared if and only the ref update fails, which
	 * allows for easy retries in case of lock failure.
	 *
	 * @return the result of attempting to update the ref.
	 * @throws java.io.IOException
	 *             if there was an error reading from or writing to the
	 *             repository.
	 */
	public RefUpdate.Result save() throws IOException {
		ObjectId newId = write();
		if (newId == null) {
			return RefUpdate.Result.NO_CHANGE;
		}
		try (ObjectInserter inserter = db.newObjectInserter()) {
			RefUpdate.Result result = updateRef(newId);
			switch (result) {
				case FAST_FORWARD:
				case NEW:
				case NO_CHANGE:
					pending.clear();
					break;
				default:
					break;
			}
			return result;
		} finally {
			close();
		}
	}

	/**
	 * Save pending certificates to the store in an existing batch ref update.
	 * <p>
	 * One commit is created per certificate added with
	 * {@link #put(PushCertificate, PersonIdent)}, in order of identity
	 * timestamps, all commits are flushed, and a single command is added to the
	 * batch.
	 * <p>
	 * The cached ref value and pending list are <em>not</em> cleared. If the
	 * ref update succeeds, the caller is responsible for calling
	 * {@link #close()} and/or {@link #clear()}.
	 *
	 * @param batch
	 *            update to save to.
	 * @return whether a command was added to the batch.
	 * @throws java.io.IOException
	 *             if there was an error reading from or writing to the
	 *             repository.
	 */
	public boolean save(BatchRefUpdate batch) throws IOException {
		ObjectId newId = write();
		if (newId == null || newId.equals(commit)) {
			return false;
		}
		batch.addCommand(new ReceiveCommand(
				commit != null ? commit : ObjectId.zeroId(), newId, REF_NAME));
		return true;
	}

	/**
	 * Clear pending certificates added with {@link #put(PushCertificate,
	 * PersonIdent)}.
	 */
	public void clear() {
		pending.clear();
	}

	private ObjectId write() throws IOException {
		if (pending.isEmpty()) {
			return null;
		}
		if (reader == null) {
			load();
		}
		sortPending(pending);

		ObjectId curr = commit;
		DirCache dc = newDirCache();
		try (ObjectInserter inserter = db.newObjectInserter()) {
			for (PendingCert pc : pending) {
				curr = saveCert(inserter, dc, pc, curr);
			}
			inserter.flush();
			return curr;
		}
	}

	private static void sortPending(List<PendingCert> pending) {
		Collections.sort(pending, new Comparator<PendingCert>() {
			@Override
			public int compare(PendingCert a, PendingCert b) {
				return Long.signum(
						a.ident.getWhen().getTime() - b.ident.getWhen().getTime());
			}
		});
	}

	private DirCache newDirCache() throws IOException {
		if (commit != null) {
			return DirCache.read(reader, commit.getTree());
		}
		return DirCache.newInCore();
	}

	private ObjectId saveCert(ObjectInserter inserter, DirCache dc,
			PendingCert pc, ObjectId curr) throws IOException {
		Map<String, ReceiveCommand> byRef;
		if (pc.matching != null) {
			byRef = new HashMap<>();
			for (ReceiveCommand cmd : pc.matching) {
				if (byRef.put(cmd.getRefName(), cmd) != null) {
					throw new IllegalStateException();
				}
			}
		} else {
			byRef = null;
		}

		DirCacheEditor editor = dc.editor();
		String certText = pc.cert.toText() + pc.cert.getSignature();
		final ObjectId certId = inserter.insert(OBJ_BLOB, certText.getBytes(UTF_8));
		boolean any = false;
		for (ReceiveCommand cmd : pc.cert.getCommands()) {
			if (byRef != null && !commandsEqual(cmd, byRef.get(cmd.getRefName()))) {
				continue;
			}
			any = true;
			editor.add(new PathEdit(pathName(cmd.getRefName())) {
				@Override
				public void apply(DirCacheEntry ent) {
					ent.setFileMode(FileMode.REGULAR_FILE);
					ent.setObjectId(certId);
				}
			});
		}
		if (!any) {
			return curr;
		}
		editor.finish();
		CommitBuilder cb = new CommitBuilder();
		cb.setAuthor(pc.ident);
		cb.setCommitter(pc.ident);
		cb.setTreeId(dc.writeTree(inserter));
		if (curr != null) {
			cb.setParentId(curr);
		} else {
			cb.setParentIds(Collections.<ObjectId> emptyList());
		}
		cb.setMessage(buildMessage(pc.cert));
		return inserter.insert(OBJ_COMMIT, cb.build());
	}

	private static boolean commandsEqual(ReceiveCommand c1, ReceiveCommand c2) {
		if (c1 == null || c2 == null) {
			return c1 == c2;
		}
		return c1.getRefName().equals(c2.getRefName())
				&& c1.getOldId().equals(c2.getOldId())
				&& c1.getNewId().equals(c2.getNewId());
	}

	private RefUpdate.Result updateRef(ObjectId newId) throws IOException {
		RefUpdate ru = db.updateRef(REF_NAME);
		ru.setExpectedOldObjectId(commit != null ? commit : ObjectId.zeroId());
		ru.setNewObjectId(newId);
		ru.setRefLogIdent(pending.get(pending.size() - 1).ident);
		ru.setRefLogMessage(JGitText.get().storePushCertReflog, false);
		try (RevWalk rw = new RevWalk(reader)) {
			return ru.update(rw);
		}
	}

	private TreeWalk newTreeWalk(String refName) throws IOException {
		if (commit == null) {
			return null;
		}
		return TreeWalk.forPath(reader, pathName(refName), commit.getTree());
	}

	static String pathName(String refName) {
		return refName + "@{cert}"; //$NON-NLS-1$
	}

	private static String buildMessage(PushCertificate cert) {
		StringBuilder sb = new StringBuilder();
		if (cert.getCommands().size() == 1) {
			sb.append(MessageFormat.format(
					JGitText.get().storePushCertOneRef,
					cert.getCommands().get(0).getRefName()));
		} else {
			sb.append(MessageFormat.format(
					JGitText.get().storePushCertMultipleRefs,
					Integer.valueOf(cert.getCommands().size())));
		}
		return sb.append('\n').toString();
	}
}
