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

import com.atlassian.bitbucket.mesh.git.builder.AbstractGitProcessBuilder;
import com.atlassian.bitbucket.mesh.git.builder.GitProcess;
import com.atlassian.bitbucket.mesh.git.builder.GitProcessBuilder;

import javax.annotation.Nonnull;
import java.io.File;
import java.util.LinkedHashSet;
import java.util.Set;

import static java.util.Objects.requireNonNull;

public class DefaultGitCommitBuilder extends AbstractGitProcessBuilder<GitCommitBuilder> implements GitCommitBuilder {

    private final Set<String> paths;
    
    private boolean all;
    private File file;
    private String message;
    private boolean quiet;
    private GitCommitVerify verify;

    public DefaultGitCommitBuilder(GitProcessBuilder builder) {
        super(builder.command("commit"));

        paths = new LinkedHashSet<>();
        verify = GitCommitVerify.DEFAULT;
    }

    @Nonnull
    @Override
    public GitCommitBuilder all(boolean value) {
        all = value;

        return self();
    }

    @Nonnull
    @Override
    public GitProcess<Void> build() {
        return buildWithLoggingHandler();
    }

    @Nonnull
    @Override
    public GitCommitBuilder clearPaths() {
        paths.clear();

        return self();
    }

    @Nonnull
    @Override
    public GitCommitBuilder message(@Nonnull File value) {
        file = requireNonNull(value, "message");

        return self();
    }

    @Nonnull
    @Override
    public GitCommitBuilder message(@Nonnull String value) {
        message = requireNonBlank(value, "message");

        return self();
    }

    @Nonnull
    @Override
    public GitCommitBuilder path(String value) {
        addIfNotBlank(paths, value);

        return self();
    }

    @Nonnull
    @Override
    public GitCommitBuilder paths(String value, String... values) {
        addIfNotBlank(paths, value, values);

        return self();
    }

    @Nonnull
    @Override
    public GitCommitBuilder paths(@Nonnull Iterable<String> values) {
        addIfNotBlank(paths, requireNonNull(values, "paths"));

        return self();
    }

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

        return self();
    }

    @Nonnull
    @Override
    public GitCommitBuilder verify(@Nonnull GitCommitVerify value) {
        verify = requireNonNull(value, "verify");

        return self();
    }

    @Override
    protected void applyArguments() {
        if (all) {
            builder.argument("-a");
        }
        if (file == null) {
            builder.argument("-m")
                    .argument(message);
        } else {
            builder.argument("-F")
                    .argument(file.getAbsolutePath());
        }
        if (quiet) {
            builder.argument("-q");
        }
        verify.getFlag().ifPresent(builder::argument);

        builder.argument("--");
        paths.forEach(builder::rawArgument);
    }

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