package com.bocloud.ims.common.utils;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Pattern;

/**
 * IP工具类
 *
 * @author sxp
 * @since 2023/6/3
 */
public class IpUtils {
    private static Logger logger = LoggerFactory.getLogger(IpUtils.class);

    /**
     * IPv4地址的正则表达式匹配模式
     * <p>
     * xxx.xxx.xxx.xxx <br>
     * xxx的取值范围是:0~255
     * </p>
     */
    private static final Pattern IP_PATTERN = Pattern
            .compile("((2[0-4]\\d|25[0-5]|[01]?\\d\\d?)\\.){3}(2[0-4]\\d|25[0-5]|[01]?\\d\\d?)");

    /**
     * 检验IPv4地址的合法性
     *
     * @author Shawpin Shi
     * @since Apr 11, 2017
     */
    public static boolean isValidIPv4(String ip) {
        if (ip == null) {
            return false;
        }
        return IP_PATTERN.matcher(ip).matches();
    }

    /**
     * 将IP地址转换为一个256进制的long整数
     *
     * @author Shawpin Shi
     * @since 2017/10/12
     */
    public static long ip2LongForV4(String ip) {
        if (!isValidIPv4(ip)) {
            throw new RuntimeException("IpUtils.ip2LongForV4:传入的IP地址[" + ip + "]无效，请检查！");
        }

        String[] ipNum = ip.split("\\.");
        Long[] ipArray = new Long[4];
        for (int i = 0, len = ipNum.length; i < len; i++) {
            ipArray[i] = Long.parseLong(ipNum[i]);
        }

        long result = ipArray[3] & 0xFF;
        result |= ((ipArray[2] << 8)) & 0xFF00;
        result |= ((ipArray[1] << 16)) & 0xFF0000;
        result |= ((ipArray[0] << 24)) & 0xFF000000;

        return result;
    }

    /**
     * 将一个256进制的long整数转换为对应的IP地址
     *
     * @author Shawpin Shi
     * @since 2017/10/12
     */
    public static String long2IpForV4(long ipLongNum) {
        int ip1 = (int) (ipLongNum >> 24) & 0xFF;
        int ip2 = (int) (ipLongNum >> 16) & 0xFF;
        int ip3 = (int) (ipLongNum >> 8) & 0xFF;
        int ip4 = (int) ipLongNum & 0xff;

        StringBuilder sb = new StringBuilder();
        sb.append(ip1).append('.');
        sb.append(ip2).append('.');
        sb.append(ip3).append('.');
        sb.append(ip4);

        return sb.toString();
    }

    /**
     * 查找两个IP地址之间的IP(ipv4)
     *
     * @author sxp
     * @since 2023/6/3
     */
    public static List<String> findIPsForIpv4(String startIp, String endIp) {
        long startNumber = ip2LongForV4(startIp);
        long endNumber = ip2LongForV4(endIp) + 1;
        int size = (int) (endNumber - startNumber + 1);
        List<String> ips = new ArrayList<>(size);

        for (long i = startNumber; i < endNumber; i++) {
            ips.add(long2IpForV4(i));
        }

        return ips;
    }
}
