package com.atlassian.stash.internal.scm.git.command.blame;

import com.atlassian.bitbucket.i18n.I18nService;
import com.atlassian.stash.internal.scm.git.command.AbstractGitCommandBuilder;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.scm.CommandExitHandler;
import com.atlassian.bitbucket.scm.CommandOutputHandler;
import com.atlassian.bitbucket.scm.git.command.GitCommand;
import com.atlassian.bitbucket.scm.git.command.GitScmCommandBuilder;
import com.atlassian.bitbucket.scm.git.command.blame.GitBlameBuilder;
import com.atlassian.bitbucket.util.PageRequest;

import javax.annotation.Nonnull;

public class DefaultGitBlameBuilder extends AbstractGitCommandBuilder<GitBlameBuilder> implements GitBlameBuilder {

    private final BlameFormat format;
    private final I18nService i18nService;
    private final Repository repository;

    private int end;
    private boolean endIsOffset;
    private String file;
    private String rev;
    private int start;
    private boolean useDefaultExitHandler;

    public DefaultGitBlameBuilder(GitScmCommandBuilder builder, I18nService i18nService, Repository repository,
                                  BlameFormat format) {
        super(builder);

        this.format = format;
        this.i18nService = i18nService;
        this.repository = repository;

        useDefaultExitHandler = true;
    }

    @Nonnull
    @Override
    public <T> GitCommand<T> build(@Nonnull CommandOutputHandler<T> outputHandler) {
        if (useDefaultExitHandler) {
            builder.exitHandler(new BlameCommandExitHandler(i18nService, repository, this, outputHandler, start));
        }

        return super.build(outputHandler);
    }

    @Nonnull
    @Override
    public GitBlameBuilder clearRange() {
        end = start = 0;
        endIsOffset = false;

        return self();
    }

    @Nonnull
    @Override
    public GitBlameBuilder defaultExitHandler() {
        useDefaultExitHandler = true;

        return self();
    }

    @Nonnull
    @Override
    public GitBlameBuilder exitHandler(@Nonnull CommandExitHandler value) {
        super.exitHandler(value);

        useDefaultExitHandler = false;

        return self();
    }

    @Nonnull
    @Override
    public DefaultGitBlameBuilder file(String value) {
        file = value;

        return self();
    }

    @Nonnull
    @Override
    public DefaultGitBlameBuilder range(@Nonnull PageRequest value) {
        end = format.toOffset(value.getLimit());
        endIsOffset = true;
        start = format.toLine(value.getStart());

        return self();
    }

    @Nonnull
    @Override
    public GitBlameBuilder range(int start, int end, boolean endIsOffset) {
        this.end = end;
        this.endIsOffset = endIsOffset;
        this.start = start;

        return self();
    }

    @Nonnull
    @Override
    public DefaultGitBlameBuilder rev(String value) {
        rev = value;

        return self();
    }

    @Override
    protected void applyArguments() {
        builder.argument(format.getFlag());

        if (start > 0 && end > 0) {
            StringBuilder rangeBuilder = new StringBuilder().append(start).append(",");
            if (endIsOffset) {
                rangeBuilder.append("+");
            }
            rangeBuilder.append(end);

            builder.argument("-L").argument(rangeBuilder.toString());
        }
        if (rev != null) {
            builder.argument(rev);
        }
        if (file != null) {
            builder.argument("--").argument(file);
        }
    }

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