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

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;

public class DefaultGitPackObjectsBuilder
        extends AbstractGitProcessBuilder<GitPackObjectsBuilder>
        implements GitPackObjectsBuilder {

    private boolean all;
    private String baseName;
    private boolean deltaBaseOffset;
    private boolean incremental;
    private boolean local;
    private boolean nonEmpty;
    private boolean reuseDelta;
    private boolean revs;
    private boolean stdout;
    private boolean thin;
    private boolean unpacked;

    public DefaultGitPackObjectsBuilder(GitProcessBuilder builder) {
        super(builder.command("pack-objects"));

        reuseDelta = true; //The git default
        stdout = true; //Unless a baseName is specified, write the pack to stdout
    }

    @Nonnull
    @Override
    public GitPackObjectsBuilder all(boolean value) {
        all = value;
        if (value) {
            revs = true; //--all implies --revs
            unpacked = false;
        }

        return self();
    }

    @Nonnull
    @Override
    public GitPackObjectsBuilder baseName(String value) {
        baseName = StringUtils.trimToNull(value);
        stdout = baseName == null;

        return self();
    }

    @Nonnull
    @Override
    public GitPackObjectsBuilder deltaBaseOffset(boolean value) {
        deltaBaseOffset = value;

        return self();
    }

    @Nonnull
    @Override
    public GitPackObjectsBuilder incremental(boolean value) {
        incremental = value;

        return self();
    }

    @Nonnull
    @Override
    public GitPackObjectsBuilder local(boolean value) {
        local = value;

        return self();
    }

    @Nonnull
    @Override
    public GitPackObjectsBuilder nonEmpty(boolean value) {
        nonEmpty = value;

        return self();
    }

    @Nonnull
    @Override
    public GitPackObjectsBuilder reuseDelta(boolean value) {
        reuseDelta = value;

        return self();
    }

    @Nonnull
    @Override
    public GitPackObjectsBuilder revs(boolean value) {
        revs = value;
        if (!value) {
            all = false;
            unpacked = false;
        }

        return self();
    }

    @Nonnull
    @Override
    public GitPackObjectsBuilder thin(boolean value) {
        thin = value;
        return self();
    }

    @Nonnull
    @Override
    public GitPackObjectsBuilder unpacked(boolean value) {
        unpacked = value;
        if (value) {
            all = false;
            revs = true; //--unpacked implies --revs
        }

        return self();
    }

    @Override
    protected void applyArguments() {
        if (deltaBaseOffset) {
            builder.argument("--delta-base-offset");
        }
        if (nonEmpty) {
            builder.argument("--non-empty");
        }
        if (local) {
            builder.argument("--local");
        }
        if (incremental) {
            builder.argument("--incremental");
        }
        if (!reuseDelta) {
            builder.argument("--no-reuse-delta");
        }
        if (revs) {
            builder.argument("--revs");
            if (all) {
                builder.argument("--all");
            } else if (unpacked) {
                builder.argument("--unpacked");
            }
        }
        if (stdout) {
            builder.argument("--stdout");
        } else {
            builder.argument(baseName);
        }
        if (thin) {
            builder.argument("--thin");
        }
    }

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