package com.atlassian.stash.internal.pull;

import com.atlassian.bitbucket.pull.PullRequest;
import com.atlassian.bitbucket.pull.PullRequestMergeRequest;
import com.atlassian.bitbucket.pull.PullRequestMergeVeto;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;

import javax.annotation.Nonnull;
import java.util.Collection;
import java.util.List;
import java.util.Map;

import static com.google.common.base.Preconditions.checkNotNull;

public class SimpleMergeRequest implements InternalMergeRequest {

    private final Map<String, Object> context;
    private final boolean dryRun;
    private final String message;
    private final PullRequest pullRequest;
    private final List<PullRequestMergeVeto> vetoes;

    private SimpleMergeRequest(Builder builder) {
        context = builder.context.build();
        dryRun = builder.dryRun;
        message = builder.message;
        pullRequest = builder.pullRequest;

        vetoes = Lists.newArrayList();
    }

    @Nonnull
    @Override
    public Map<String, Object> getContext() {
        return context;
    }

    @Override
    public String getMessage() {
        return message;
    }

    @Nonnull
    @Override
    public PullRequest getPullRequest() {
        return pullRequest;
    }

    @Nonnull
    @Override
    public Collection<PullRequestMergeVeto> getVetoes() {
        return ImmutableList.copyOf(vetoes);
    }

    @Override
    public boolean isDryRun() {
        return dryRun;
    }

    @Override
    public boolean isVetoed() {
        return !vetoes.isEmpty();
    }

    @Override
    public void veto(@Nonnull String summary, @Nonnull String detailedMessage) {
        vetoes.add(new SimplePullRequestMergeVeto(summary, detailedMessage));
    }

    public static class Builder {

        private final ImmutableMap.Builder<String, Object> context;
        private final PullRequest pullRequest;

        private boolean dryRun;
        private String message;

        public Builder(PullRequest pullRequest) {
            this.pullRequest = checkNotNull(pullRequest, "pullRequest");

            context = ImmutableMap.builder();
            dryRun = true; //When only a pull request is supplied, assume we're doing a dry run
        }

        public Builder(@Nonnull PullRequest pullRequest, @Nonnull PullRequestMergeRequest mergeRequest) {
            this(pullRequest);

            message = checkNotNull(mergeRequest, "mergeRequest").getMessage();
            dryRun = false; //When a PullRequestMergeRequest is supplied, assume it's not a dry run

            context.putAll(mergeRequest.getContext());
        }

        @Nonnull
        public SimpleMergeRequest build() {
            return new SimpleMergeRequest(this);
        }

        @Nonnull
        public Builder context(@Nonnull String key, @Nonnull String value) {
            context.put(key, value);

            return this;
        }

        @Nonnull
        public Builder context(@Nonnull Map<String, Object> value) {
            context.putAll(value);

            return this;
        }

        @Nonnull
        public Builder dryRun(boolean value) {
            dryRun = value;

            return this;
        }

        @Nonnull
        public Builder message(@Nonnull String value) {
            message = value;

            return this;
        }
    }
}
