package com.atlassian.bitbucket.pull;

import com.atlassian.bitbucket.project.Project;
import com.atlassian.bitbucket.repository.Repository;
import com.atlassian.bitbucket.util.BuilderSupport;

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

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

/**
 * @since 4.9
 */
public abstract class AbstractPullRequestMergeConfigRequest {

    private final Project project;
    private final Repository repository;
    private final String scmId;

    protected AbstractPullRequestMergeConfigRequest(AbstractBuilder<?, ?> builder) {
        project = builder.project;
        repository = builder.repository;
        scmId = builder.scmId;
    }

    @Nonnull
    public Optional<Project> getProject() {
        return ofNullable(project);
    }

    @Nonnull
    public Optional<Repository> getRepository() {
        return ofNullable(repository);
    }

    @Nonnull
    public Optional<String> getScmId() {
        return ofNullable(scmId);
    }

    public abstract static class AbstractBuilder<B extends AbstractBuilder<B, R>, R extends AbstractPullRequestMergeConfigRequest>
            extends BuilderSupport {

        private final Project project;
        private final Repository repository;
        private final String scmId;

        protected AbstractBuilder(@Nonnull Project project, @Nonnull String scmId) {
            this.project = requireNonNull(project, "project");
            this.scmId = requireNonBlank(scmId, "scmId");

            repository = null;
        }

        protected AbstractBuilder(@Nonnull Repository repository) {
            this.repository = requireNonNull(repository, "repository");

            project = null;
            scmId = null;
        }

        protected AbstractBuilder(@Nonnull String scmId) {
            this.scmId = requireNonBlank(scmId, "scmId");

            project = null;
            repository = null;
        }

        @Nonnull
        public abstract R build();

        @Nonnull
        protected abstract B self();
    }
}
