package com.atlassian.bitbucket.mesh.network;

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

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

import static java.util.Objects.requireNonNull;

/**
 * @since 1.4
 */
public class PartitionReplicaMigration {

    private final String partitionId;
    private final MeshNode sourceNode;
    private final MeshNode targetNode;

    private PartitionReplicaMigration(Builder builder) {
        partitionId = requireNonNull(builder.partitionId, "partitionId");
        sourceNode = requireNonNull(builder.sourceNode, "sourceNode");
        targetNode = requireNonNull(builder.targetNode, "targetNode");
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null || getClass() != o.getClass()) {
            return false;
        }
        PartitionReplicaMigration that = (PartitionReplicaMigration) o;
        return partitionId.equals(that.partitionId) &&
                sourceNode.equals(that.sourceNode) &&
                targetNode.equals(that.targetNode);
    }

    @Nonnull
    public String getPartitionId() {
        return partitionId;
    }

    @Nonnull
    public MeshNode getSourceNode() {
        return sourceNode;
    }

    @Nonnull
    public MeshNode getTargetNode() {
        return targetNode;
    }

    @Override
    public int hashCode() {
        return Objects.hash(partitionId, sourceNode, targetNode);
    }

    @Nonnull
    public RpcPartitionReplicaMigration toPartitionReplicaMigration() {
        return RpcPartitionReplicaMigration.newBuilder()
                .setPartition(partitionId)
                .setSourceNodeId(sourceNode.getId())
                .setTargetNodeId(targetNode.getId())
                .build();
    }

    public static class Builder extends BuilderSupport {

        private String partitionId;
        private MeshNode sourceNode;
        private MeshNode targetNode;

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

        @Nonnull
        public Builder partition(@Nonnull String value) {
            partitionId = requireNonBlank(value, "partition");
            return this;
        }

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

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