package com.zm.order.tool.server.manager;

import org.springframework.util.Assert;

/**
 * @Author nianchang
 * @Date 2020/3/23 14:16
 */
public final class RoutingAlgorithm {

    public static int routeDB(long userId, int dbSize) {
        if (dbSize < 0) {
            throw new IllegalArgumentException("routing db size can't lt 0");
        }
        if (dbSize == 0) {
            return 0;
        }
        int hashCode = hashcode(userId);
        return hashCode & (dbSize - 1);
    }

    public static int routeTB(long userId, int dbSize, int tbSize) {
        if (dbSize < 0 || tbSize < 0) {
            throw new IllegalArgumentException("routing db & tb size can't lt 0");
        }
        if (dbSize == 0 || tbSize == 0) {
            return 0;
        }
        int hashCode = hashcode(userId);
        return (hashCode / dbSize) & (tbSize - 1);
    }
    
    private static int hashcode(long userId) {
        int hashCode = String.valueOf(userId).hashCode();
        if (hashCode < 0) {
            hashCode = -hashCode;
        }
        return hashCode;
    }
    
    public static int oldRouteDb(long userId, int dbSize) {
        if (userId < 0) {
            userId = -userId;
        }
        return (int)userId % dbSize;
    }

    public static int oldRouteTb(long userId, int dbSize, int tbSize) {
        if (userId < 0) {
            userId = -userId;
        }
        return (int)(userId / dbSize) % tbSize;
    }


    /**
     * db index exception
     */
    private static final String DB_ROUTE_EXCEPTION = "route db size must gt 0";

    /**
     * tb index exception
     */
    private static final String TB_ROUTE_EXCEPTION = "route db & tb size must gt 0";


    /**
     * db route index
     *
     * @param userId 用户id
     * @param dbSize 数据库数量
     * @return 数据库分片
     */
    public static int routeDb(long userId, int dbSize) {
        Assert.isTrue((dbSize > 0), DB_ROUTE_EXCEPTION);
        int hashCode = hashcode(userId);
        return hashCode & (dbSize - 1);
    }

    /**
     * tb route index
     *
     * @param userId 用户id
     * @param dbSize 数据库数量
     * @param tbSize 数据表数量
     * @return 数据表分片
     */
    public static int routeTb(long userId, int dbSize, int tbSize) {
        Assert.isTrue((dbSize > 0 && tbSize > 0), TB_ROUTE_EXCEPTION);
        int hashCode = hashcode(userId);
        return (hashCode / dbSize) & (tbSize - 1);
    }
}
