package com.atlassian.stash.internal.scm.git.command.blame;

/**
 * Defines formats supported by {@code git blame} <i>other than the default</i>. {@code null} will provide the default
 * output.
 */
public enum BlameFormat {

    /**
     * Incremental output provides only blame information--it omits the content lines. Additionally, incremental output
     * emits blame information in reverse commit order rather than line order. This means spans related to the latest
     * revisions are output first, regardless of where they are in the file, and the spans must be sorted to produce
     * ordered blame.
     */
    INCREMENTAL("--incremental") {

        @Override
        public int toOffset(int limit) {
            //Incremental only returns blame, no content, and the list of Blame elements for paged lines is itself
            //_not paged_. As a result, we only want to add an extra line to the offset for other formats.
            return limit;
        }
    },
    /**
     * Porcelain output provides both blame information and file contents. The blame format is the same as is used for
     * {@link #INCREMENTAL incremental} output, when a commit is first encountered, followed by the content from the
     * file prefixed with a tab. Unlike incremental output Porcelain output emits blame in line order, so spans do not
     * need to be manually sorted to produce ordered blame.
     */
    PORCELAIN("--porcelain") {

        @Override
        public int toOffset(int limit) {
            //Add an extra line to the offset so that we can detect whether we're on the last page or not.
            return limit + 1;
        }
    };
    
    private final String flag;

    private BlameFormat(String flag) {
        this.flag = flag;
    }

    /**
     * Retrieves the command line flag for {@code git blame} for specifying this format.
     *
     * @return the command line flag
     */
    public String getFlag() {
        return flag;
    }

    public int toLine(int start) {
        return start + 1;
    }

    public abstract int toOffset(int limit);
}
