package com.app.framework.core.utils.number;

import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/**
 * 开闭区间工具类
 */
public class RangeUtil {

    /**
     * 开闭区间正则表达式
     */
    private static final Pattern NUM_RANGE_PATTERN = Pattern.compile("[\\[|\\(]\\s?\\d+\\.?\\d*\\s?,\\s?\\d+\\.?\\d*\\s?[\\)|\\]]");

    /**
     * 左半区间正则表达式
     */
    private static final Pattern LEFT_NUM_RANGE_PATTERN = Pattern.compile("[\\[|\\(]\\s?\\d+\\.?\\d*\\s?,\\s?[\\)|\\]]");

    /**
     * 右半区间正则表达式
     */
    private static final Pattern RIGHT_NUM_RANGE_PATTERN = Pattern.compile("[\\[|\\(],\\s?\\d+\\.?\\d*\\s?[\\)|\\]]");

    /**
     * 判断是否为有效的数字区间范围
     * @param numRange 数字区间,支持小数,左右皆允许为空,eg:(0, 2] or [1, 4] or [100, ]
     * @return boolean
     */
    public static boolean isValidNumRange(String numRange) {
        return NUM_RANGE_PATTERN.matcher(numRange).matches()
                || LEFT_NUM_RANGE_PATTERN.matcher(numRange).matches()
                || RIGHT_NUM_RANGE_PATTERN.matcher(numRange).matches();
    }

    /**
     * 判断数值是否在区间范围内
     * @param number 数值
     * @param numRange 开闭区间,支持小数,左右皆允许为空,eg:(0, 2] or [1, 4] or [100, ]
     * @return boolean
     */
    public static boolean inNumRange(BigDecimal number, String numRange) {
        Objects.requireNonNull(numRange);

        if (!isValidNumRange(numRange)) {
            return false;
        }

        String[] pairs = numRange.split(",");

        // 获取开闭区间的最小值和最大值
        List<String> rangeNums = Arrays.stream(pairs).map(str -> str.replaceAll("[(|)|\\[|\\]]", "").trim()).collect(Collectors.toList());
        BigDecimal minValue = "".equals(rangeNums.get(0)) ? null : new BigDecimal(rangeNums.get(0));
        BigDecimal maxValue = "".equals(rangeNums.get(1)) ? null : new BigDecimal(rangeNums.get(1));

        // 判定数值是否大于最小值
        boolean minMatched = (minValue == null) || (pairs[0].startsWith("[") ? number.compareTo(minValue) >= 0 : number.compareTo(minValue) > 0);
        // 判定数值是否小于最大值
        boolean maxMatched = (maxValue == null) || (pairs[1].endsWith("]") ? number.compareTo(maxValue) <= 0 : number.compareTo(maxValue) < 0);

        return minMatched && maxMatched;
    }

    public static void main(String[] args) {
//        System.out.println(inNumRange(1, "(0, 2]"));
//        System.out.println(inNumRange(1, "(, 2]"));
//        System.out.println(inNumRange(1, "(1, 4]"));
//        System.out.println(inNumRange(1, "(0, ]"));
//        System.out.println();
//        System.out.println(inNumRange(190, "[100, 400]"));
//        System.out.println(inNumRange(BigDecimal.valueOf(300), "[100, 400)"));

        System.out.println(inNumRange(BigDecimal.valueOf(800.89), "[0, )"));

    }

}
