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

import com.atlassian.bitbucket.mesh.git.GitAgent;
import com.atlassian.bitbucket.mesh.git.ref.Branch;
import com.atlassian.bitbucket.mesh.util.ShaUtils;

import javax.annotation.Nonnull;
import javax.annotation.concurrent.NotThreadSafe;

import static java.util.Objects.requireNonNull;

@NotThreadSafe
public class DefaultPullRequestRefs implements PullRequestRefs {

    private final GitAgent agent;
    private final String darkFromId;
    private final String darkMergeId;
    private final String publicFromId;
    private final String publicMergeId;
    private final PullRequest pullRequest;

    private String darkFrom;
    private String darkMerge;
    private String publicFrom;
    private String publicMerge;

    public DefaultPullRequestRefs(GitAgent agent, PullRequest pullRequest) {
        this.agent = requireNonNull(agent, "agent");
        this.pullRequest = requireNonNull(pullRequest, "pullRequest");

        PullRequestRefBuilder builder = PullRequestRefBuilder.darkRef(pullRequest.getRepository()).id(pullRequest);
        darkFromId = builder.type(PullRequestRefType.FROM).toRef();
        darkMergeId = builder.type(PullRequestRefType.MERGE).toRef();

        builder = PullRequestRefBuilder.publicRef().id(pullRequest);
        publicFromId = builder.type(PullRequestRefType.FROM).toRef();
        publicMergeId = builder.type(PullRequestRefType.MERGE).toRef();
    }

    @Nonnull
    @Override
    public String getDarkFrom() {
        return darkFromId;
    }

    @Nonnull
    @Override
    public String getDarkMerge() {
        return darkMergeId;
    }

    @Nonnull
    @Override
    public String getPublicFrom() {
        return publicFromId;
    }

    @Nonnull
    @Override
    public String getPublicMerge() {
        return publicMergeId;
    }

    @Override
    public boolean isDarkFromOutdated() {
        return !ShaUtils.hashesMatch(pullRequest.getFromRef().getLatestCommit(), resolveDarkFrom());
    }

    @Override
    public boolean isPublicFromOutdated() {
        return !ShaUtils.hashesMatch(pullRequest.getFromRef().getLatestCommit(), resolvePublicFrom());
    }

    @Override
    public String resolveDarkFrom() {
        if (darkFrom == null) {
            darkFrom = resolve(darkFromId);
        }
        return darkFrom;
    }

    @Override
    public String resolveDarkMerge() {
        if (darkMerge == null) {
            darkMerge = resolve(darkMergeId);
        }
        return darkMerge;
    }

    @Override
    public String resolvePublicFrom() {
        if (publicFrom == null) {
            publicFrom = resolve(publicFromId);
        }
        return publicFrom;
    }

    @Override
    public String resolvePublicMerge() {
        if (publicMerge == null) {
            publicMerge = resolve(publicMergeId);
        }
        return publicMerge;
    }

    private String resolve(String refId) {
        Branch resolved = agent.resolveBranch(pullRequest.getToRef().getRepository(), refId, true);
        return resolved == null ? null : resolved.getLatestCommit();
    }
}
