package com.atlassian.bitbucket.scm;

import com.atlassian.bitbucket.repository.RefType;
import com.atlassian.bitbucket.repository.StandardRefType;

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

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

/**
 * Describes a ref to {@link ScmCommandFactory#resolveRef(ResolveRefCommandParameters) resolve}.
 * <p>
 * If it is known whether a requested ref is a branch or a tag, the caller is <i>encouraged</i> to specify the
 * {@link Builder#type type} to allow the SCM to optimize resolving the ref. If the ref type is unknown, the
 * type should be left {@code null}.
 *
 * @see StandardRefType
 * @since 4.6
 */
public class ResolveRefCommandParameters extends AbstractCommandParameters {

    private final String refId;
    private final RefType type;

    private ResolveRefCommandParameters(Builder builder) {
        refId = builder.refId;
        type = builder.type;
    }

    /**
     * @return the branch IDs to resolve
     */
    @Nonnull
    public String getRefId() {
        return refId;
    }

    /**
     * @return an optional {@link RefType}, used to limit scope for matching the {@link #getRefId refId}, which may
     *         {@code empty()} but never {@code null}
     */
    @Nonnull
    public Optional<RefType> getType() {
        return ofNullable(type);
    }

    public static class Builder {

        private final String refId;

        private RefType type;

        public Builder(@Nonnull String refId) {
            this.refId = requireNonNull(refId, "refId");
        }

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

        @Nonnull
        public Builder type(@Nullable RefType value) {
            type = value;

            return this;
        }
    }
}
