package com.atlassian.bitbucket.scm.git.command.diff;

/**
 * Defines headers which may appear in {@code git diff} output. These will appear after the {@code diff --git} banner
 * and before any hunks.
*/
public enum GitDiffHeader {

    /**
     * Defines the source path for a copied file.
     */
    COPY_FROM("copy from", GitDiffHeaderType.PATH, GitDiffTarget.SOURCE),
    /**
     * Defines the destination path for a copied file.
     */
    COPY_TO("copy to", GitDiffHeaderType.PATH, GitDiffTarget.DESTINATION),
    /**
     * Defines the file mode a source file had before it was deleted.
     */
    DELETED_FILE_MODE("deleted file mode", GitDiffHeaderType.MODE, GitDiffTarget.SOURCE),
    /**
     * Defines the percentage of dissimilarity between a source file and a copied/renamed/moved destination file.
     */
    DISSIMILARITY_INDEX("dissimilarity index", GitDiffHeaderType.PERCENTAGE),
    /**
     * Defines git index data, such as content hashes, for the source and destination files.
     */
    INDEX("index", GitDiffHeaderType.INDEX),
    /**
     * Defines the file mode for a newly-added destination file.
     */
    NEW_FILE_MODE("new file mode", GitDiffHeaderType.MODE, GitDiffTarget.DESTINATION),
    /**
     * Defines the new mode for a destination file.
     */
    NEW_MODE("new mode", GitDiffHeaderType.MODE, GitDiffTarget.DESTINATION),
    /**
     * Defines the original mode for a source file.
     */
    OLD_MODE("old mode", GitDiffHeaderType.MODE, GitDiffTarget.SOURCE),
    /**
     * Defines the source path for a renamed/moved file.
     */
    RENAME_FROM("rename from", GitDiffHeaderType.PATH, GitDiffTarget.SOURCE),
    /**
     * Defines the destination path for a renamed/moved file.
     */
    RENAME_TO("rename to", GitDiffHeaderType.PATH, GitDiffTarget.DESTINATION),
    /**
     * Defines the percentage of similarity between a source file and a copied/renamed/moved destination file.
     */
    SIMILARITY_INDEX("similarity index", GitDiffHeaderType.PERCENTAGE);

    private final String key;
    private final GitDiffTarget target;
    private final GitDiffHeaderType type;

    GitDiffHeader(String key, GitDiffHeaderType type) {
        this(key, type, GitDiffTarget.NONE);
    }
    
    GitDiffHeader(String key, GitDiffHeaderType type, GitDiffTarget target) {
        type.verify(target);

        this.key = key;
        this.target = target;
        this.type = type;
    }

    /**
     * Retrieves the key identifying this header in an output line.
     * <p>
     * Note: Header keys may contain one or more spaces, so {@code indexOf}-based splitting should not be used.
     * 
     * @return the header key
     */
    public String getKey() {
        return key;
    }

    /**
     * Retrieves the target to which the value of this header applies. The {@link #getType() header type} will indicate
     * whether a specific target is available.
     * 
     * @return the header target
     */
    public GitDiffTarget getTarget() {
        return target;
    }

    /**
     * Retrieves the type of data provided by the {@link #getValue(String) header value}. The type also indicates
     * whether a specific {@link #getTarget() target} is related to this header.
     *
     * @return the header type
     */
    public GitDiffHeaderType getType() {
        return type;
    }

    /**
     * Removes the leading {@link #getKey() key} from the provided line and returns the value.
     *
     * @param line the line to split
     * @return the value part of the line
     */
    public String getValue(String line) {
        return line.substring(key.length() + 1); //Drop the space after the header
    }
}
