package com.atlassian.bitbucket.scm.git;

import com.atlassian.bitbucket.content.ContentTreeNode;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;

/**
 * Defines the types of objects which may be returned by {@code git cat-file -t}.
 */
public enum GitObjectType {

    /**
     * A blob, which is a {@link ContentTreeNode.Type#FILE file} of some type.
     */
    BLOB("blob", ContentTreeNode.Type.FILE),
    /**
     * A commit, which is a {@link ContentTreeNode.Type#SUBMODULE submodule}.
     */
    COMMIT("commit", ContentTreeNode.Type.SUBMODULE),
    /**
     * A tag, which is a reference to a specific {@link #COMMIT commit} and may be annotated, signed or lightweight.
     */
    TAG("tag"),
    /**
     * A tree, which is a {@link ContentTreeNode.Type#DIRECTORY directory}.
     */
    TREE("tree", ContentTreeNode.Type.DIRECTORY);

    private final ContentTreeNode.Type nodeType;
    private final String objectType;

    GitObjectType(@Nonnull String objectType) {
        this(objectType, null);
    }

    GitObjectType(@Nonnull String objectType, @Nullable ContentTreeNode.Type nodeType) {
        this.objectType = objectType;
        this.nodeType = nodeType;
    }

    /**
     * Determines the {@code GitObjectType} for the provided {@code git cat-file -t} object type.
     *
     * @param objectType the {@code git} object type
     * @return the {@code GitObjectType} associated with the provided {@code git} object type
     * @throws IllegalArgumentException if no {@code GitObjectType} matches the provided {@code git} object type
     */
    @Nonnull
    public static GitObjectType fromObjectType(String objectType) {
        for (GitObjectType value : values()) {
            if (objectType.equals(value.getObjectType())) {
                return value;
            }
        }
        throw new IllegalArgumentException("Object type [" + objectType + "] is not a known GitObjectType");
    }

    /**
     * Retrieves the {@link ContentTreeNode.Type} for this object type, which may be {@code null} for object types
     * that are not readily expressed in as content nodes.
     *
     * @return the content node type for this object type, or {@code null} if this object should not be shown in the
     *         content tree
     */
    @Nullable
    public ContentTreeNode.Type getNodeType() {
        return nodeType;
    }

    /**
     * Retrieves the type used by {@code git cat-file -t} to represent this object type.
     *
     * @return the {@code git} object type
     */
    @Nonnull
    public String getObjectType() {
        return objectType;
    }
}
