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

import com.atlassian.bitbucket.mesh.git.AbstractParameters;
import com.atlassian.bitbucket.mesh.repository.Repository;
import com.google.common.collect.ImmutableList;

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.List;
import java.util.Objects;

import static java.util.Objects.requireNonNull;

public class UpdateRefsParameters extends AbstractParameters {

    private final boolean dereferenceSymbolicRefs;
    private final Repository repository;
    private final boolean transactional;
    private final List<ProposedRefUpdate> updates;

    private UpdateRefsParameters(Builder builder) {
        super(builder);

        dereferenceSymbolicRefs = builder.dereferenceSymbolicRefs;
        repository = builder.repository;
        transactional = builder.transactional;
        updates = builder.updates.build();
    }

    @Nonnull
    public Repository getRepository() {
        return repository;
    }

    @Nonnull
    public List<ProposedRefUpdate> getUpdates() {
        return updates;
    }

    public boolean isDereferenceSymbolicRefs() {
        return dereferenceSymbolicRefs;
    }

    public boolean isTransactional() {
        return transactional;
    }

    public static class Builder extends AbstractBuilder<Builder, UpdateRefsParameters> {

        private final Repository repository;
        private final ImmutableList.Builder<ProposedRefUpdate> updates;

        private boolean dereferenceSymbolicRefs;
        private boolean transactional;

        public Builder(@Nonnull Repository repository) {
            this.repository = requireNonNull(repository, "repository");

            dereferenceSymbolicRefs = true;
            updates = ImmutableList.builder();
        }

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

        @Nonnull
        public Builder dereferenceSymbolicRefs(boolean value) {
            dereferenceSymbolicRefs = value;

            return self();
        }

        @Nonnull
        public Builder transactional(boolean value) {
            transactional = value;

            return self();
        }

        @Nonnull
        public Builder updates(@Nullable Iterable<ProposedRefUpdate> values) {
            addIf(Objects::nonNull, updates, values);

            return self();
        }

        @Nonnull
        public Builder updates(@Nullable ProposedRefUpdate value, @Nullable ProposedRefUpdate... values) {
            addIf(Objects::nonNull, updates, value, values);

            return self();
        }

        @Nonnull
        @Override
        protected Builder self() {
            return this;
        }
    }
}
