package com.cube.consistency;

/**
 * Consistency levels for read and write operations in Cube database.
 * Similar to Apache Cassandra's consistency levels.
 */
public enum ConsistencyLevel {
    
    /**
     * ONE - Only one replica must respond.
     * Fastest but least consistent.
     */
    ONE(1, "Requires response from 1 replica"),
    
    /**
     * TWO - Two replicas must respond.
     * Balanced consistency and performance.
     */
    TWO(2, "Requires response from 2 replicas"),
    
    /**
     * THREE - Three replicas must respond.
     */
    THREE(3, "Requires response from 3 replicas"),
    
    /**
     * QUORUM - Majority of replicas must respond.
     * (Replication Factor / 2) + 1
     * Strong consistency for most use cases.
     */
    QUORUM(-1, "Requires response from majority of replicas"),
    
    /**
     * ALL - All replicas must respond.
     * Strongest consistency but slowest.
     */
    ALL(-2, "Requires response from all replicas"),
    
    /**
     * LOCAL_ONE - One replica in local datacenter.
     * Used in multi-datacenter deployments.
     */
    LOCAL_ONE(1, "Requires response from 1 local replica"),
    
    /**
     * LOCAL_QUORUM - Quorum in local datacenter.
     */
    LOCAL_QUORUM(-1, "Requires response from local quorum"),
    
    /**
     * ANY - At least one node must respond (may be hinted handoff).
     * Fastest writes, weakest consistency.
     */
    ANY(1, "Requires response from any node (including hints)");
    
    private final int requiredReplicas;
    private final String description;
    
    ConsistencyLevel(int requiredReplicas, String description) {
        this.requiredReplicas = requiredReplicas;
        this.description = description;
    }
    
    /**
     * Calculate the number of required responses for a given replication factor.
     * 
     * @param replicationFactor Total number of replicas
     * @return Number of responses required
     */
    public int getRequiredResponses(int replicationFactor) {
        switch (this) {
            case QUORUM:
            case LOCAL_QUORUM:
                return (replicationFactor / 2) + 1;
            case ALL:
                return replicationFactor;
            case ANY:
            case ONE:
            case LOCAL_ONE:
                return 1;
            case TWO:
                return Math.min(2, replicationFactor);
            case THREE:
                return Math.min(3, replicationFactor);
            default:
                return requiredReplicas;
        }
    }
    
    /**
     * Check if this consistency level requires quorum.
     */
    public boolean isQuorum() {
        return this == QUORUM || this == LOCAL_QUORUM;
    }
    
    /**
     * Check if this consistency level is local to datacenter.
     */
    public boolean isLocal() {
        return this == LOCAL_ONE || this == LOCAL_QUORUM;
    }
    
    /**
     * Check if hinted handoff is acceptable for this level.
     */
    public boolean allowsHints() {
        return this == ANY;
    }
    
    public String getDescription() {
        return description;
    }
    
    @Override
    public String toString() {
        return name() + " (" + description + ")";
    }
}
