/*
 * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com>
 * Copyright (C) 2009-2010, Google Inc.
 * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com>
 * Copyright (C) 2006, 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.internal.storage.file;

import static org.eclipse.jgit.lib.Constants.HEAD;
import static org.eclipse.jgit.lib.Constants.LOCK_SUFFIX;
import static org.eclipse.jgit.lib.Constants.R_HEADS;
import static org.eclipse.jgit.lib.Constants.R_NOTES;
import static org.eclipse.jgit.lib.Constants.R_REFS;
import static org.eclipse.jgit.lib.Constants.R_REMOTES;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.text.MessageFormat;

import org.eclipse.jgit.internal.JGitText;
import org.eclipse.jgit.lib.ConfigConstants;
import org.eclipse.jgit.lib.Constants;
import org.eclipse.jgit.lib.CoreConfig;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.RefUpdate;
import org.eclipse.jgit.lib.ReflogEntry;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.util.FileUtils;

/**
 * Utility for writing reflog entries using the traditional one-file-per-log
 * format.
 */
public class ReflogWriter {

	/**
	 * Get the ref name to be used for when locking a ref's log for rewriting.
	 *
	 * @param name
	 *            name of the ref, relative to the Git repository top level
	 *            directory (so typically starts with refs/).
	 * @return the name of the ref's lock ref.
	 */
	public static String refLockFor(String name) {
		return name + LOCK_SUFFIX;
	}

	private final RefDirectory refdb;

	private final boolean forceWrite;

	/**
	 * Create writer for ref directory.
	 *
	 * @param refdb
	 *            a {@link org.eclipse.jgit.internal.storage.file.RefDirectory}
	 *            object.
	 */
	public ReflogWriter(RefDirectory refdb) {
		this(refdb, false);
	}

	/**
	 * Create writer for ref directory.
	 *
	 * @param refdb
	 *            a {@link org.eclipse.jgit.internal.storage.file.RefDirectory}
	 *            object.
	 * @param forceWrite
	 *            true to write to disk all entries logged, false to respect the
	 *            repository's config and current log file status.
	 */
	public ReflogWriter(RefDirectory refdb, boolean forceWrite) {
		this.refdb = refdb;
		this.forceWrite = forceWrite;
	}

	/**
	 * Create the log directories.
	 *
	 * @throws java.io.IOException
	 * @return this writer.
	 */
	public ReflogWriter create() throws IOException {
		FileUtils.mkdir(refdb.logsDir);
		FileUtils.mkdir(refdb.logsRefsDir);
		FileUtils.mkdir(
				new File(refdb.logsRefsDir, R_HEADS.substring(R_REFS.length())));
		return this;
	}

	/**
	 * Write the given entry to the ref's log.
	 *
	 * @param refName
	 *            a {@link java.lang.String} object.
	 * @param entry
	 *            a {@link org.eclipse.jgit.lib.ReflogEntry} object.
	 * @return this writer
	 * @throws java.io.IOException
	 */
	public ReflogWriter log(String refName, ReflogEntry entry)
			throws IOException {
		return log(refName, entry.getOldId(), entry.getNewId(), entry.getWho(),
				entry.getComment());
	}

	/**
	 * Write the given entry information to the ref's log
	 *
	 * @param refName
	 *            ref name
	 * @param oldId
	 *            old object id
	 * @param newId
	 *            new object id
	 * @param ident
	 *            a {@link org.eclipse.jgit.lib.PersonIdent}
	 * @param message
	 *            reflog message
	 * @return this writer
	 * @throws java.io.IOException
	 */
	public ReflogWriter log(String refName, ObjectId oldId,
			ObjectId newId, PersonIdent ident, String message) throws IOException {
		byte[] encoded = encode(oldId, newId, ident, message);
		return log(refName, encoded);
	}

	/**
	 * Write the given ref update to the ref's log.
	 *
	 * @param update
	 *            a {@link org.eclipse.jgit.lib.RefUpdate}
	 * @param msg
	 *            reflog message
	 * @param deref
	 *            whether to dereference symbolic refs
	 * @return this writer
	 * @throws java.io.IOException
	 */
	public ReflogWriter log(RefUpdate update, String msg,
			boolean deref) throws IOException {
		ObjectId oldId = update.getOldObjectId();
		ObjectId newId = update.getNewObjectId();
		Ref ref = update.getRef();

		PersonIdent ident = update.getRefLogIdent();
		if (ident == null)
			ident = new PersonIdent(refdb.getRepository());
		else
			ident = new PersonIdent(ident);

		byte[] rec = encode(oldId, newId, ident, msg);
		if (deref && ref.isSymbolic()) {
			log(ref.getName(), rec);
			log(ref.getLeaf().getName(), rec);
		} else
			log(ref.getName(), rec);

		return this;
	}

	private byte[] encode(ObjectId oldId, ObjectId newId, PersonIdent ident,
			String message) {
		StringBuilder r = new StringBuilder();
		r.append(ObjectId.toString(oldId));
		r.append(' ');
		r.append(ObjectId.toString(newId));
		r.append(' ');
		r.append(ident.toExternalString());
		r.append('\t');
		r.append(
				message.replace("\r\n", " ") //$NON-NLS-1$ //$NON-NLS-2$
						.replace("\n", " ")); //$NON-NLS-1$ //$NON-NLS-2$
		r.append('\n');
		return Constants.encode(r.toString());
	}

	private FileOutputStream getFileOutputStream(File log) throws IOException {
		try {
			return new FileOutputStream(log, true);
		} catch (FileNotFoundException err) {
			File dir = log.getParentFile();
			if (dir.exists()) {
				throw err;
			}
			if (!dir.mkdirs() && !dir.isDirectory()) {
				throw new IOException(MessageFormat
						.format(JGitText.get().cannotCreateDirectory, dir));
			}
			return new FileOutputStream(log, true);
		}
	}

	private ReflogWriter log(String refName, byte[] rec) throws IOException {
		File log = refdb.logFor(refName);
		boolean write = forceWrite
				|| shouldAutoCreateLog(refName)
				|| log.isFile();
		if (!write)
			return this;

		WriteConfig wc = refdb.getRepository().getConfig().get(WriteConfig.KEY);
		try (FileOutputStream out = getFileOutputStream(log)) {
			if (wc.getFSyncRefFiles()) {
				FileChannel fc = out.getChannel();
				ByteBuffer buf = ByteBuffer.wrap(rec);
				while (0 < buf.remaining()) {
					fc.write(buf);
				}
				fc.force(true);
			} else {
				out.write(rec);
			}
		}
		return this;
	}

	private boolean shouldAutoCreateLog(String refName) {
		Repository repo = refdb.getRepository();
		CoreConfig.LogRefUpdates value = repo.isBare()
				? CoreConfig.LogRefUpdates.FALSE
				: CoreConfig.LogRefUpdates.TRUE;
		value = repo.getConfig().getEnum(ConfigConstants.CONFIG_CORE_SECTION,
				null, ConfigConstants.CONFIG_KEY_LOGALLREFUPDATES, value);
		if (value != null) {
			switch (value) {
			case FALSE:
				break;
			case TRUE:
				return refName.equals(HEAD) || refName.startsWith(R_HEADS)
						|| refName.startsWith(R_REMOTES)
						|| refName.startsWith(R_NOTES);
			case ALWAYS:
				return refName.equals(HEAD) || refName.startsWith(R_REFS);
			default:
				break;
			}
		}
		return false;
	}
}