/*
 * Copyright (C) 2022,  Matthias Sohn <matthias.sohn@sap.com> 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.lib;

import static org.eclipse.jgit.lib.Constants.OBJECT_ID_ABBREV_STRING_LENGTH;
import static org.eclipse.jgit.lib.TypedConfigGetter.UNSET_INT;

import java.text.MessageFormat;

import org.eclipse.jgit.api.errors.InvalidConfigurationException;
import org.eclipse.jgit.internal.JGitText;

/**
 * Git configuration option <a
 * href="https://git-scm.com/docs/git-config#Documentation/git-config.txt-coreabbrev">
 * core.abbrev</a>
 *
 * @since 6.1
 */
public final class AbbrevConfig {
	private static final String VALUE_NO = "no"; //$NON-NLS-1$

	private static final String VALUE_AUTO = "auto"; //$NON-NLS-1$

	/**
	 * The minimum value of abbrev
	 */
	public static final int MIN_ABBREV = 4;

	/**
	 * Cap configured core.abbrev to range between minimum of 4 and number of
	 * hex-digits of a full object id.
	 *
	 * @param len
	 *            configured number of hex-digits to abbreviate object ids to
	 * @return core.abbrev capped to range between minimum of 4 and number of
	 *         hex-digits of a full object id
	 */
	public static int capAbbrev(int len) {
		return Math.min(Math.max(MIN_ABBREV, len),
				Constants.OBJECT_ID_STRING_LENGTH);
	}

	/**
	 * No abbreviation
	 */
	public final static AbbrevConfig NO = new AbbrevConfig(
			Constants.OBJECT_ID_STRING_LENGTH);

	/**
	 * Parse string value of core.abbrev git option for a given repository
	 *
	 * @param repo
	 *            repository
	 * @return the parsed AbbrevConfig
	 * @throws InvalidConfigurationException
	 *             if value of core.abbrev is invalid
	 */
	public static AbbrevConfig parseFromConfig(Repository repo)
			throws InvalidConfigurationException {
		Config config = repo.getConfig();
		String value = config.getString(ConfigConstants.CONFIG_CORE_SECTION,
				null, ConfigConstants.CONFIG_KEY_ABBREV);
		if (value == null || value.equalsIgnoreCase(VALUE_AUTO)) {
			return auto(repo);
		}
		if (value.equalsIgnoreCase(VALUE_NO)) {
			return NO;
		}
		try {
			int len = config.getIntInRange(ConfigConstants.CONFIG_CORE_SECTION,
					ConfigConstants.CONFIG_KEY_ABBREV, MIN_ABBREV,
					Constants.OBJECT_ID_STRING_LENGTH, UNSET_INT);
			if (len == UNSET_INT) {
				// Unset was checked above. If we get UNSET_INT here, then
				// either the value was UNSET_INT, or it was an invalid value
				// (not an integer, or out of range), and EGit's
				// ReportingTypedGetter caught the exception and has logged a
				// warning. In either case we should fall back to some sane
				// default.
				len = OBJECT_ID_ABBREV_STRING_LENGTH;
			}
			return new AbbrevConfig(len);
		} catch (IllegalArgumentException e) {
			throw new InvalidConfigurationException(MessageFormat
					.format(JGitText.get().invalidCoreAbbrev, value), e);
		}
	}

	/**
	 * An appropriate value is computed based on the approximate number of
	 * packed objects in a repository, which hopefully is enough for abbreviated
	 * object names to stay unique for some time.
	 *
	 * @param repo
	 *            the repository the AbbrevConfig shall be computed for
	 * @return appropriate value computed based on the approximate number of
	 *         packed objects in a repository
	 */
	private static AbbrevConfig auto(Repository repo) {
		long count = repo.getObjectDatabase().getApproximateObjectCount();
		if (count == -1) {
			return new AbbrevConfig(OBJECT_ID_ABBREV_STRING_LENGTH);
		}
		// find msb, round to next power of 2
		int len = 63 - Long.numberOfLeadingZeros(count) + 1;
		// With the order of 2^len objects, we expect a collision at
		// 2^(len/2). But we also care about hex chars, not bits, and
		// there are 4 bits per hex. So all together we need to divide
		// by 2; but we also want to round odd numbers up, hence adding
		// one before dividing.
		len = (len + 1) / 2;
		// for small repos use at least fallback length
		return new AbbrevConfig(Math.max(len, OBJECT_ID_ABBREV_STRING_LENGTH));
	}

	/**
	 * All other possible abbreviation lengths. Valid range 4 to number of
	 * hex-digits of an unabbreviated object id (40 for SHA1 object ids, jgit
	 * doesn't support SHA256 yet).
	 */
	private int abbrev;

	/**
	 * Create an {@code AbbrevConfig}
	 *
	 * @param abbrev
	 *            abbreviation length
	 */
	private AbbrevConfig(int abbrev) {
		this.abbrev = capAbbrev(abbrev);
	}

	/**
	 * Get the configured abbreviation length for object ids.
	 *
	 * @return the configured abbreviation length for object ids
	 */
	public int get() {
		return abbrev;
	}

	@Override
	public String toString() {
		return Integer.toString(abbrev);
	}
}