package com.atlassian.bitbucket.mesh.repository;

import com.atlassian.bitbucket.mesh.rpc.v1.RpcInconsistentReplica;
import com.google.common.collect.ImmutableMap;

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

import static java.util.Objects.requireNonNull;

public class MarkInconsistentParameters {

    private final boolean complete;
    private final Map<String, Long> inconsistentReplicas;
    private final boolean fromControlPlane;

    private MarkInconsistentParameters(Builder builder) {
        complete = builder.complete;
        inconsistentReplicas = builder.inconsistentReplicas.build();
        fromControlPlane = builder.fromControlPlane;
    }

    /**
     * @return a map of repository ID to version the repository replica is inconsistent with
     */
    @Nonnull
    public Map<String, Long> getInconsistentReplicas() {
        return inconsistentReplicas;
    }

    /**
     * @return {@code true} if the provided set of {@link #getInconsistentReplicas() inconsistent replicas} is
     *         the <em>complete</em> set of inconsistent replicas
     */
    public boolean isComplete() {
        return complete;
    }

    /**
     * @return {@code true} if the update is initiated by control plane
     */
    public boolean isFromControlPlane() {
        return fromControlPlane;
    }

    public static class Builder {

        private final ImmutableMap.Builder<String, Long> inconsistentReplicas;

        private boolean complete;
        private boolean fromControlPlane;

        public Builder() {
            inconsistentReplicas = ImmutableMap.builder();
        }

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

        @Nonnull
        public Builder complete(boolean value) {
            complete = value;
            return this;
        }

        @Nonnull
        public Builder inconsistentReplica(@Nonnull String repositoryId, long version) {
            requireNonNull(repositoryId, "repositoryId");

            inconsistentReplicas.put(repositoryId, version);
            return this;
        }

        @Nonnull
        public Builder inconsistentReplicas(@Nonnull Iterable<RpcInconsistentReplica> values) {
            requireNonNull(values, "inconsistentReplicas");

            values.forEach(value -> inconsistentReplicas.put(value.getRepository(), value.getVersion()));
            return this;
        }

        @Nonnull
        public Builder inconsistentReplicas(@Nonnull Map<String, Long> values) {
            requireNonNull(values, "inconsistentReplicas");

            inconsistentReplicas.putAll(values);
            return this;
        }

        @Nonnull
        public Builder fromControlPlane(boolean value) {
            fromControlPlane = value;
            return this;
        }
    }
}
