package com.atlassian.bitbucket.mesh.git.ref;

import com.atlassian.bitbucket.mesh.repository.Repository;

import javax.annotation.Nonnull;

import static java.util.Objects.requireNonNull;

/**
 * Common abstraction between reference types like {@link Branch branches} and {@link Tag tags}.
 */
public interface Ref {

    /**
     * @param refId the ref ID to check
     * @return {@code true} if the provided ref ID is a dark ref
     */
    static boolean isDark(@Nonnull String refId) {
        requireNonNull(refId, "refId");
        return !refId.startsWith("refs/") && !"HEAD".equals(refId);
    }

    /**
     * The absolute identifier of this reference, which should never be ambiguous within the backing {@link Repository}.
     * <p>
     * When performing operations which accept a commit ID, this is the value that should be used to ensure there are
     * no ambiguities.
     *
     * @return the reference's absolute identifier
     */
    @Nonnull
    String getId();

    /**
     * The ID of the commit at the tip of this ref.
     *
     * @return the tip commit's ID
     */
    @Nonnull
    String getLatestCommit();

    /**
     * The ID of the referenced object. For branches and simple tags, this will be identical to
     * {@link #getLatestCommit()}. For annotated tags, this will be {@link Tag#getHash()}.
     *
     * @return the referenced object ID
     */
    @Nonnull
    String getObjectId();

    /**
     * @return the type of ref
     */
    @Nonnull
    RefType getType();

    /**
     * @return {@code true} if the provided ref ID is a dark ref
     */
    default boolean isDark() {
        return isDark(getId());
    }
}
