package com.atlassian.bitbucket.mesh.git.pull;

import com.atlassian.bitbucket.mesh.repository.Repository;
import com.atlassian.bitbucket.mesh.rpc.v1.RpcPullRequest;
import com.atlassian.bitbucket.mesh.util.BuilderSupport;

import javax.annotation.Nonnull;

import static java.util.Objects.requireNonNull;

public class PullRequest {

    private final PullRequestRef fromRef;
    private final long id;
    private final PullRequestState state;
    private final PullRequestRef toRef;
    private final int version;

    private PullRequest(Builder builder) {
        fromRef = builder.fromRef;
        id = builder.id;
        state = builder.state;
        toRef = builder.toRef;
        version = builder.version;
    }

    @Nonnull
    public PullRequestRef getFromRef() {
        return fromRef;
    }

    public long getId() {
        return id;
    }

    @Nonnull
    public Repository getRepository() {
        return getToRef().getRepository();
    }

    @Nonnull
    public PullRequestState getState() {
        return state;
    }

    @Nonnull
    public PullRequestRef getToRef() {
        return toRef;
    }

    public int getVersion() {
        return version;
    }

    public boolean isCrossRepository() {
        return !fromRef.getRepository().equals(toRef.getRepository());
    }

    public boolean isOpen() {
        return state == PullRequestState.OPEN;
    }

    @Nonnull
    public RpcPullRequest toPullRequest() {
        return RpcPullRequest.newBuilder()
                .setFromRef(fromRef.toPullRequestRef())
                .setId(id)
                .setState(state.toRpc())
                .setToRef(toRef.toPullRequestRef())
                .setVersion(version)
                .build();
    }

    @Override
    public String toString() {
        return id + "@" + version;
    }

    public static class Builder extends BuilderSupport {

        private final long id;
        private final int version;

        private PullRequestRef fromRef;
        private PullRequestState state;
        private PullRequestRef toRef;

        public Builder(@Nonnull PullRequest pullRequest) {
            fromRef = requireNonNull(pullRequest, "pullRequest").getFromRef();
            id = pullRequest.getId();
            state = pullRequest.getState();
            toRef = pullRequest.getToRef();
            version = pullRequest.getVersion();
        }

        public Builder(long id, int version) {
            this.id = id;
            this.version = version;
        }

        @Nonnull
        public PullRequest build() {
            requireNonNull(fromRef, "fromRef");
            requireNonNull(state, "state");
            requireNonNull(toRef, "toRef");

            return new PullRequest(this);
        }

        @Nonnull
        public Builder fromRef(@Nonnull PullRequestRef value) {
            fromRef = requireNonNull(value, "fromRef");

            return this;
        }

        @Nonnull
        public Builder state(@Nonnull PullRequestState value) {
            state = value;

            return this;
        }

        @Nonnull
        public Builder toRef(@Nonnull PullRequestRef value) {
            toRef = requireNonNull(value, "toRef");

            return this;
        }
    }
}
