package com.atlassian.bitbucket.commit;

import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.util.BuilderSupport;
import org.apache.commons.lang3.StringUtils;

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

import static java.util.Objects.requireNonNull;
import static java.util.Optional.ofNullable;

/**
 * Request for searching for commit comment {@link CommitDiscussionCommentAnchor anchors}.
 * The purpose and behaviour of each field is described on its accessor.
 * @since 4.7
 */
public class CommitCommentAnchorSearchRequest {

    private final String commitId;
    private final String parentId;
    private final String path;
    private final Long pullRequestId;
    private final Repository repository;

    private CommitCommentAnchorSearchRequest(@Nonnull Builder builder) {
        commitId = builder.commitId;
        parentId = builder.parentId;
        path = builder.path;
        pullRequestId = builder.pullRequestId;
        repository = builder.repository;
    }

    /**
     * @return the ID of the commit within the repository
     */
    @Nonnull
    public String getCommitId() {
        return commitId;
    }

    /**
     * For merge commits which have diffs to multiple parents the parent ID can be used to specified which diff
     * the anchor should be on.
     * @return the ID for a parent commit
     */
    @Nonnull
    public Optional<String> getParentId() {
        return ofNullable(parentId);
    }

    /**
     * @return the path of the file on which the anchors must be
     */
    @Nonnull
    public String getPath() {
        return path;
    }

    /**
     * For comments made on a pull request commit the pull request ID can be used to identify the pull request.
     * If no ID is provided only anchors for comments which were not made on any pull request will be retrieved.
     * @return the ID of a pull request on which the anchor was created
     */
    @Nonnull
    public Optional<Long> getPullRequestId() {
        return ofNullable(pullRequestId);
    }

    /**
     * @return the repository containing the commit
     */
    @Nonnull
    public Repository getRepository() {
        return repository;
    }

    public static class Builder extends BuilderSupport {

        private final String commitId;
        private final String path;
        private final Repository repository;

        private String parentId;
        private Long pullRequestId;

        public Builder(@Nonnull Repository repository, @Nonnull String commitId, @Nonnull String path) {
            this.repository = requireNonNull(repository, "repository");
            this.commitId = checkNotBlank(commitId, "commitId");
            this.path = checkNotBlank(path, "path");
        }

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

        @Nonnull
        public Builder parentId(@Nullable String value) {
            parentId = StringUtils.trimToNull(value);
            return this;
        }

        @Nonnull
        public Builder pullRequestId(@Nullable Long value) {
            pullRequestId = value;
            return this;
        }
    }
}
