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

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

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

import static java.util.Objects.requireNonNull;

public class DefaultGitRepackBuilder extends AbstractGitProcessBuilder<GitRepackBuilder> implements GitRepackBuilder {

    private GitRepackAll all;
    private int depth;
    private boolean local;
    private boolean keepUnreachable;
    private String maxPackSize;
    private boolean noReuseDeltas;
    private boolean noReuseObjects;
    private boolean noUpdateServerInfo;
    private boolean prune;
    private boolean quiet;
    private String unpackUnreachable;
    private int window;
    private int windowMemory;
    private boolean writeBitmapIndex;

    public DefaultGitRepackBuilder(GitProcessBuilder builder) {
        super(builder.command("repack"));

        all = GitRepackAll.DEFAULT;
    }

    @Nonnull
    @Override
    public GitRepackBuilder all(@Nonnull GitRepackAll value) {
        all = requireNonNull(value, "all");

        return self();
    }

    @Nonnull
    @Override
    public GitRepackBuilder depth(int value) {
        depth = value;

        return self();
    }

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

        return self();
    }

    @Nonnull
    @Override
    public GitRepackBuilder keepUnreachable(boolean value) {
        keepUnreachable = value;

        return self();
    }

    @Nonnull
    @Override
    public GitRepackBuilder maxPackSize(String value) {
        maxPackSize = value;

        return self();
    }

    @Nonnull
    @Override
    public GitRepackBuilder prune(boolean value) {
        prune = value;

        return self();
    }

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

        return self();
    }

    @Nonnull
    @Override
    public GitRepackBuilder reuseDeltas(boolean value) {
        noReuseDeltas = !value;

        return self();
    }

    @Nonnull
    @Override
    public GitRepackBuilder reuseObjects(boolean value) {
        noReuseObjects = !value;

        return self();
    }

    @Nonnull
    @Override
    public GitRepackBuilder unpackUnreachable(@Nullable String value) {
        unpackUnreachable = value;

        return self();
    }

    @Nonnull
    @Override
    public GitRepackBuilder updateServerInfo(boolean value) {
        noUpdateServerInfo = !value;

        return self();
    }

    @Nonnull
    @Override
    public GitRepackBuilder window(int value) {
        window = value;

        return self();
    }

    @Nonnull
    @Override
    public GitRepackBuilder windowMemory(int value) {
        windowMemory = value;

        return self();
    }

    @Nonnull
    @Override
    public GitRepackBuilder writeBitmapIndex(boolean value) {
        writeBitmapIndex = value;

        return self();
    }

    @Override
    protected void applyArguments() {
        if (all.isFlagged()) {
            builder.argument(all.getFlag());
        }
        if (prune) {
            builder.argument("-d");
        }
        if (local) {
            builder.argument("-l");
        }
        if (noReuseObjects) {
            builder.argument("-F");
        } else if (noReuseDeltas) {
            //-F implies -f, so only set this if noReuseObjects is false
            builder.argument("-f");
        }
        if (quiet) {
            builder.argument("-q");
        }
        if (noUpdateServerInfo) {
            builder.argument("-n");
        }
        if (window > 0) {
            builder.argument("--window=" + window);
        }
        if (depth > 0) {
            builder.argument("--depth=" + depth);
        }
        if (windowMemory > 0) {
            builder.argument("--windowMemory=" + window);
        }
        if (maxPackSize != null) {
            builder.argument("--max-pack-size=" + maxPackSize);
        }
        if (writeBitmapIndex) {
            builder.argument("--write-bitmap-index");
        }
        if (unpackUnreachable != null) {
            builder.argument("--unpack-unreachable=" + unpackUnreachable);
        }
        if (keepUnreachable) {
            builder.argument("--keep-unreachable");
        }
    }

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