package com.atlassian.bitbucket.mesh.git.builder.diff;

import com.atlassian.bitbucket.mesh.rpc.v1.RpcDiffOutput;

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

import static java.util.Objects.requireNonNull;

/**
 * Enumerates output modes for {@code diff-core} commands like {@code diff}, {@code diff-tree} and {@code log}.
 * These modes are mutually exclusive, so they are defined as an enumeration rather than having distinct options
 * on the associated builder.
 */
public enum GitDiffOutput {

    /**
     * Checks the diff for whitespace errors, using the process return code to signal whether any are found.
     */
    CHECK("--check"),
    /**
     * Allows the command to produce its default output, without providing any specific argument to adjust it.
     */
    DEFAULT(null),
    /**
     * Shows only the names of changed files.
     */
    NAME_ONLY("--name-only"),
    /**
     * Shows the names of changed files and a status describing the change.
     */
    NAME_STATUS("--name-status"),
    /**
     * Generate patch output.
     */
    PATCH("--patch"),
    /**
     * Suppresses all diff output.
     */
    SUPPRESS("--no-patch");

    private final String flag;

    GitDiffOutput(String flag) {
        this.flag = flag;
    }

    @Nonnull
    public static GitDiffOutput fromRpc(@Nonnull RpcDiffOutput rpc) {
        switch(requireNonNull(rpc, "rpc")) {
            case OUTPUT_CHECK:
                return CHECK;
            case OUTPUT_NAME_ONLY:
                return NAME_ONLY;
            case OUTPUT_NAME_STATUS:
                return NAME_STATUS;
            case OUTPUT_PATCH:
                return PATCH;
            case OUTPUT_SUPPRESS:
                return SUPPRESS;
            default:
                return DEFAULT;
        }
    }

    /**
     * @return the command line flag for this output mode, if any
     */
    @Nullable
    public String getFlag() {
        return flag;
    }

    /**
     * @return {@code true} if this mode requires a command line flag; otherwise, {@code false}
     */
    public boolean isFlagged() {
        return flag != null;
    }
}
