package com.atlassian.stash.internal.pull;

import com.atlassian.bitbucket.commit.Commit;
import com.atlassian.bitbucket.commit.CommitRequest;
import com.atlassian.bitbucket.pull.AbstractPullRequestActivityVisitor;
import com.atlassian.bitbucket.pull.PullRequestActivityVisitor;
import com.atlassian.bitbucket.pull.PullRequestMergeActivity;
import com.atlassian.stash.internal.commit.InternalCommitService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.Nonnull;
import java.util.Optional;

/**
 * Enriches {@link PullRequestMergeActivity merge activities} by adding full {@link Commit commits} to those for
 * which a {@link InternalPullRequestMergeActivity#getHash() merge hash} is available.
 *
 * @since 1.3
 */
@Component
public class MergePullRequestActivityEnricher implements PullRequestActivityEnricher {

    private final PullRequestActivityVisitor mergeVisitor;

    @Autowired
    public MergePullRequestActivityEnricher(InternalCommitService commitService) {
        this.mergeVisitor = new MergeActivityVisitor(commitService);
    }

    @Override
    public void enrich(@Nonnull InternalPullRequest pullRequest,
                       @Nonnull Iterable<InternalPullRequestActivity> activities) {
        for (InternalPullRequestActivity activity : activities) {
            activity.accept(mergeVisitor);
        }
    }

    private static class MergeActivityVisitor extends AbstractPullRequestActivityVisitor {

        private final InternalCommitService commitService;

        private MergeActivityVisitor(InternalCommitService commitService) {
            this.commitService = commitService;
        }

        @Override
        public void visit(@Nonnull PullRequestMergeActivity activity) {
            InternalPullRequestMergeActivity mergeActivity = (InternalPullRequestMergeActivity) activity;

            String mergeHash = mergeActivity.getHash();
            if (mergeHash != null && mergeActivity.getCommit() == null) {
                Optional<Commit> mergeCommit = commitService.findCommit(
                        new CommitRequest.Builder(mergeActivity.getPullRequest().getScopeRepository(), mergeHash)
                                    .build());
                mergeCommit.ifPresent(mergeActivity::setCommit);
            }
        }
    }
}
