package com.atlassian.bitbucket.mesh.network;

import com.atlassian.bitbucket.mesh.rpc.v1.RpcPartitionReplica;
import com.atlassian.bitbucket.mesh.util.BuilderSupport;

import javax.annotation.Nonnull;

import static java.util.Objects.requireNonNull;

public class PartitionReplica {

    private final String id;
    private final MeshNode node;

    private PartitionReplica(Builder builder) {
        id = builder.id;
        node = builder.node;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        PartitionReplica that = (PartitionReplica) o;
        return id.equals(that.id);
    }

    /**
     * @return the partition replica's identifier
     */
    @Nonnull
    public String getId() {
        return id;
    }

    /**
     * @return the Mesh node that hosts this partition replica
     */
    @Nonnull
    public MeshNode getNode() {
        return node;
    }

    @Override
    public int hashCode() {
        return id.hashCode();
    }

    /**
     * @return whether the partition replica's vote counts in quorum-based writes
     */
    public boolean isVoting() {
        return true;
    }

    @Nonnull
    public RpcPartitionReplica toPartitionReplica() {
        return RpcPartitionReplica.newBuilder()
                .setId(id)
                .setNodeId(node.getId())
                .build();
    }

    @Override
    public String toString() {
        return "PartitionReplica{" +
                "id='" + id + '\'' +
                ", node=" + node +
                '}';
    }

    public static class Builder extends BuilderSupport {

        private final String id;

        private MeshNode node;

        public Builder(@Nonnull String id, @Nonnull MeshNode node) {
            this.id = requireNonBlank(id, "id");
            this.node = requireNonNull(node, "node");
        }

        public Builder(@Nonnull PartitionReplica other) {
            requireNonNull(other, "other");

            id = requireNonNull(other.getId(), "other.id");
            node = requireNonNull(other.getNode(), "other.node");
        }

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

        @Nonnull
        public Builder node(@Nonnull MeshNode value) {
            node = requireNonNull(value, "node");
            return this;
        }
    }
}
