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

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.eclipse.jgit.lib.Constants.R_TAGS;

import java.io.IOException;
import java.net.URI;
import java.text.MessageFormat;
import java.util.List;

import org.eclipse.jgit.api.errors.ConcurrentRefUpdateException;
import org.eclipse.jgit.api.errors.GitAPIException;
import org.eclipse.jgit.api.errors.JGitInternalException;
import org.eclipse.jgit.dircache.DirCache;
import org.eclipse.jgit.dircache.DirCacheBuilder;
import org.eclipse.jgit.dircache.DirCacheEntry;
import org.eclipse.jgit.dircache.InvalidPathException;
import org.eclipse.jgit.gitrepo.RepoCommand.ManifestErrorException;
import org.eclipse.jgit.gitrepo.RepoCommand.RemoteFile;
import org.eclipse.jgit.gitrepo.RepoCommand.RemoteReader;
import org.eclipse.jgit.gitrepo.RepoCommand.RemoteUnavailableException;
import org.eclipse.jgit.gitrepo.RepoProject.CopyFile;
import org.eclipse.jgit.gitrepo.RepoProject.LinkFile;
import org.eclipse.jgit.gitrepo.internal.RepoText;
import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.Config;
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.PersonIdent;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.RefUpdate.Result;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.util.FileUtils;

/**
 * Writes .gitmodules and gitlinks of parsed manifest projects into a bare
 * repository.
 *
 * To write on a regular repository, see {@link RegularSuperprojectWriter}.
 */
class BareSuperprojectWriter {
	private static final int LOCK_FAILURE_MAX_RETRIES = 5;

	// Retry exponentially with delays in this range
	private static final int LOCK_FAILURE_MIN_RETRY_DELAY_MILLIS = 50;

	private static final int LOCK_FAILURE_MAX_RETRY_DELAY_MILLIS = 5000;

	private final Repository repo;

	private final URI targetUri;

	private final String targetBranch;

	private final RemoteReader callback;

	private final BareWriterConfig config;

	private final PersonIdent author;

	private List<ExtraContent> extraContents;

	static class BareWriterConfig {
		boolean ignoreRemoteFailures = false;

		boolean recordRemoteBranch = true;

		boolean recordSubmoduleLabels = true;

		boolean recordShallowSubmodules = true;

		static BareWriterConfig getDefault() {
			return new BareWriterConfig();
		}

		private BareWriterConfig() {
		}
	}

	static class ExtraContent {
		final String path;

		final String content;

		ExtraContent(String path, String content) {
			this.path = path;
			this.content = content;
		}
	}

	BareSuperprojectWriter(Repository repo, URI targetUri,
			String targetBranch,
			PersonIdent author, RemoteReader callback,
			BareWriterConfig config,
			List<ExtraContent> extraContents) {
		assert repo.isBare();
		this.repo = repo;
		this.targetUri = targetUri;
		this.targetBranch = targetBranch;
		this.author = author;
		this.callback = callback;
		this.config = config;
		this.extraContents = extraContents;
	}

	RevCommit write(List<RepoProject> repoProjects)
			throws GitAPIException {
		DirCache index = DirCache.newInCore();
		ObjectInserter inserter = repo.newObjectInserter();

		try (RevWalk rw = new RevWalk(repo)) {
			prepareIndex(repoProjects, index, inserter);
			ObjectId treeId = index.writeTree(inserter);
			long prevDelay = 0;
			for (int i = 0; i < LOCK_FAILURE_MAX_RETRIES - 1; i++) {
				try {
					return commitTreeOnCurrentTip(inserter, rw, treeId);
				} catch (ConcurrentRefUpdateException e) {
					prevDelay = FileUtils.delay(prevDelay,
							LOCK_FAILURE_MIN_RETRY_DELAY_MILLIS,
							LOCK_FAILURE_MAX_RETRY_DELAY_MILLIS);
					Thread.sleep(prevDelay);
					repo.getRefDatabase().refresh();
				}
			}
			// In the last try, just propagate the exceptions
			return commitTreeOnCurrentTip(inserter, rw, treeId);
		} catch (IOException | InterruptedException | InvalidPathException e) {
			throw new ManifestErrorException(e);
		}
	}

	private void prepareIndex(List<RepoProject> projects, DirCache index,
			ObjectInserter inserter) throws IOException, GitAPIException {
		Config cfg = new Config();
		StringBuilder attributes = new StringBuilder();
		DirCacheBuilder builder = index.builder();
		for (RepoProject proj : projects) {
			String name = proj.getName();
			String path = proj.getPath();
			String url = proj.getUrl();
			ObjectId objectId;
			if (ObjectId.isId(proj.getRevision())) {
				objectId = ObjectId.fromString(proj.getRevision());
			} else {
				objectId = callback.sha1(url, proj.getRevision());
				if (objectId == null && !config.ignoreRemoteFailures) {
					throw new RemoteUnavailableException(url);
				}
				if (config.recordRemoteBranch) {
					// "branch" field is only for non-tag references.
					// Keep tags in "ref" field as hint for other tools.
					String field = proj.getRevision().startsWith(R_TAGS) ? "ref" //$NON-NLS-1$
							: "branch"; //$NON-NLS-1$
					cfg.setString("submodule", name, field, //$NON-NLS-1$
							proj.getRevision());
				}

				if (config.recordShallowSubmodules
						&& proj.getRecommendShallow() != null) {
					// The shallow recommendation is losing information.
					// As the repo manifests stores the recommended
					// depth in the 'clone-depth' field, while
					// git core only uses a binary 'shallow = true/false'
					// hint, we'll map any depth to 'shallow = true'
					cfg.setBoolean("submodule", name, "shallow", //$NON-NLS-1$ //$NON-NLS-2$
							true);
				}
			}
			if (config.recordSubmoduleLabels) {
				StringBuilder rec = new StringBuilder();
				rec.append("/"); //$NON-NLS-1$
				rec.append(path);
				for (String group : proj.getGroups()) {
					rec.append(" "); //$NON-NLS-1$
					rec.append(group);
				}
				rec.append("\n"); //$NON-NLS-1$
				attributes.append(rec.toString());
			}

			URI submodUrl = URI.create(url);
			if (targetUri != null) {
				submodUrl = RepoCommand.relativize(targetUri, submodUrl);
			}
			cfg.setString("submodule", name, "path", path); //$NON-NLS-1$ //$NON-NLS-2$
			cfg.setString("submodule", name, "url", //$NON-NLS-1$ //$NON-NLS-2$
					submodUrl.toString());

			// create gitlink
			if (objectId != null) {
				DirCacheEntry dcEntry = new DirCacheEntry(path);
				dcEntry.setObjectId(objectId);
				dcEntry.setFileMode(FileMode.GITLINK);
				builder.add(dcEntry);

				for (CopyFile copyfile : proj.getCopyFiles()) {
					RemoteFile rf = callback.readFileWithMode(url,
							proj.getRevision(), copyfile.src);
					objectId = inserter.insert(Constants.OBJ_BLOB,
							rf.getContents());
					dcEntry = new DirCacheEntry(copyfile.dest);
					dcEntry.setObjectId(objectId);
					dcEntry.setFileMode(rf.getFileMode());
					builder.add(dcEntry);
				}
				for (LinkFile linkfile : proj.getLinkFiles()) {
					String link;
					if (linkfile.dest.contains("/")) { //$NON-NLS-1$
						link = FileUtils.relativizeGitPath(
								linkfile.dest.substring(0,
										linkfile.dest.lastIndexOf('/')),
								proj.getPath() + "/" + linkfile.src); //$NON-NLS-1$
					} else {
						link = proj.getPath() + "/" + linkfile.src; //$NON-NLS-1$
					}

					objectId = inserter.insert(Constants.OBJ_BLOB,
							link.getBytes(UTF_8));
					dcEntry = new DirCacheEntry(linkfile.dest);
					dcEntry.setObjectId(objectId);
					dcEntry.setFileMode(FileMode.SYMLINK);
					builder.add(dcEntry);
				}
			}
		}
		String content = cfg.toText();

		// create a new DirCacheEntry for .gitmodules file.
		DirCacheEntry dcEntry = new DirCacheEntry(
				Constants.DOT_GIT_MODULES);
		ObjectId objectId = inserter.insert(Constants.OBJ_BLOB,
				content.getBytes(UTF_8));
		dcEntry.setObjectId(objectId);
		dcEntry.setFileMode(FileMode.REGULAR_FILE);
		builder.add(dcEntry);

		if (config.recordSubmoduleLabels) {
			// create a new DirCacheEntry for .gitattributes file.
			DirCacheEntry dcEntryAttr = new DirCacheEntry(
					Constants.DOT_GIT_ATTRIBUTES);
			ObjectId attrId = inserter.insert(Constants.OBJ_BLOB,
					attributes.toString().getBytes(UTF_8));
			dcEntryAttr.setObjectId(attrId);
			dcEntryAttr.setFileMode(FileMode.REGULAR_FILE);
			builder.add(dcEntryAttr);
		}

		for (ExtraContent ec : extraContents) {
			DirCacheEntry extraDcEntry = new DirCacheEntry(ec.path);

			ObjectId oid = inserter.insert(Constants.OBJ_BLOB,
					ec.content.getBytes(UTF_8));
			extraDcEntry.setObjectId(oid);
			extraDcEntry.setFileMode(FileMode.REGULAR_FILE);
			builder.add(extraDcEntry);
		}

		builder.finish();
	}

	private RevCommit commitTreeOnCurrentTip(ObjectInserter inserter,
			RevWalk rw, ObjectId treeId)
			throws IOException, ConcurrentRefUpdateException {
		ObjectId headId = repo.resolve(targetBranch + "^{commit}"); //$NON-NLS-1$
		if (headId != null
				&& rw.parseCommit(headId).getTree().getId().equals(treeId)) {
			// No change. Do nothing.
			return rw.parseCommit(headId);
		}

		CommitBuilder commit = new CommitBuilder();
		commit.setTreeId(treeId);
		if (headId != null) {
			commit.setParentIds(headId);
		}
		commit.setAuthor(author);
		commit.setCommitter(author);
		commit.setMessage(RepoText.get().repoCommitMessage);

		ObjectId commitId = inserter.insert(commit);
		inserter.flush();

		RefUpdate ru = repo.updateRef(targetBranch);
		ru.setNewObjectId(commitId);
		ru.setExpectedOldObjectId(headId != null ? headId : ObjectId.zeroId());
		Result rc = ru.update(rw);
		switch (rc) {
		case NEW:
		case FORCED:
		case FAST_FORWARD:
			// Successful. Do nothing.
			break;
		case REJECTED:
		case LOCK_FAILURE:
			throw new ConcurrentRefUpdateException(MessageFormat.format(
					JGitText.get().cannotLock, targetBranch), ru.getRef(), rc);
		default:
			throw new JGitInternalException(
					MessageFormat.format(JGitText.get().updatingRefFailed,
							targetBranch, commitId.name(), rc));
		}

		return rw.parseCommit(commitId);
	}
}
