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

import com.atlassian.bitbucket.mesh.git.builder.AbstractGitProcessBuilder;
import com.atlassian.bitbucket.mesh.git.builder.GitProcessBuilder;
import org.apache.commons.lang3.StringUtils;

import javax.annotation.Nonnull;

import static java.util.Objects.requireNonNull;

public class DefaultGitCheckoutBuilder
        extends AbstractGitProcessBuilder<GitCheckoutBuilder>
        implements GitCheckoutBuilder {

    private String branch;
    private boolean detach;
    private boolean force;
    private GitCheckoutCreateBranchMode mode;
    private boolean reflog;
    private boolean quiet;
    private String startPoint;

    public DefaultGitCheckoutBuilder(GitProcessBuilder builder) {
        super(builder.command("checkout"));
    }

    @Nonnull
    @Override
    public GitCheckoutBuilder branch(@Nonnull String value) {
        branch = requireNonBlank(value, "branch");
        detach = false;
        mode = null;
        startPoint = null;

        return self();
    }

    @Nonnull
    @Override
    public GitCheckoutBuilder branch(@Nonnull String branch, String startPoint) {
        return branch(branch, startPoint, GitCheckoutCreateBranchMode.CREATE);
    }

    @Nonnull
    @Override
    public GitCheckoutBuilder branch(@Nonnull String branch, String startPoint,
                                     @Nonnull GitCheckoutCreateBranchMode mode) {
        this.branch = requireNonBlank(branch, "branch");
        this.mode = requireNonNull(mode, "mode");
        this.startPoint = startPoint;

        detach = false;

        return self();
    }

    @Nonnull
    @Override
    public GitCheckoutBuilder detach(@Nonnull String value) {
        branch = requireNonBlank(value, "value");
        detach = true;
        mode = null;
        startPoint = null;

        return self();
    }

    @Nonnull
    @Override
    public GitCheckoutBuilder force(boolean value) {
        force = value;

        return self();
    }

    @Nonnull
    @Override
    public GitCheckoutBuilder quiet(boolean value) {
        quiet = value;

        return self();
    }

    @Nonnull
    @Override
    public GitCheckoutBuilder reflog(boolean value) {
        reflog = value;

        return self();
    }

    @Override
    protected void applyArguments() {
        if (force) {
            builder.argument("--force");
        }
        if (quiet) {
            builder.argument("--quiet");
        }

        if (detach) {
            //git checkout --detach <commit>
            builder.argument("--detach");
            builder.commitish(branch);
        } else if (mode == null) {
            //git checkout <branch>, which will automatically detach if "branch" is a commit ID or tag
            builder.commitish(branch);
        } else {
            //git checkout [-b|-B|--orphan] <branch> <start-point>
            if (reflog) {
                builder.argument("-l");
            }
            builder.argument(mode.getFlag())
                    .argument(branch);
            if (StringUtils.isNotBlank(startPoint)) {
                builder.commitish(startPoint);
            }
        }
    }

    @Nonnull
    @Override
    protected GitCheckoutBuilder self() {
        return this;
    }
}
