package com.njcn.product.carrycapacity.util;

import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.StrUtil;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.type.TypeFactory;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import com.njcn.common.pojo.enums.response.CommonResponseEnum;
import com.njcn.common.pojo.exception.BusinessException;

import java.io.IOException;
import java.lang.reflect.Method;
import java.lang.reflect.Type;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import static java.lang.Integer.parseInt;


/**
 * @author hongawen
 * @version 1.0.0
 * @date 2021年04月12日 14:21
 */
public class PubUtils {

    private final static ObjectMapper MAPPER = new ObjectMapper();

    private static final String DATE_TIME = "yyyy-MM-dd HH:mm:ss";

    private static final String DATE = "yyyy-MM-dd";

    private static final String TIME = "HH:mm:ss";


    /**
     * 生成随机码，包含字母。--> 大写
     *
     * @param length 随机码长度
     */
    public static String randomCode(int length) {
        return RandomUtil.randomString(length).toUpperCase(Locale.ENGLISH);
    }


    /****
     * ***** ***** 验证IP是否属于某个IP段 ipSection IP段（以'-'分隔） ip 所验证的IP号码 ***** *****
     **/
    public static boolean ipExistsInRange(String ip, String ipSection) {
        ipSection = ipSection.trim();
        ip = ip.trim();
        int idx = ipSection.indexOf('-');
        String beginIp = ipSection.substring(0, idx);
        String endIp = ipSection.substring(idx + 1);
        return getIp2long(beginIp) <= getIp2long(ip) && getIp2long(ip) <= getIp2long(endIp);
    }

    private static long getIp2long(String ip) {
        ip = ip.trim();
        String[] ips = ip.split("\\.");
        long ip2long = 0L;
        for (int i = 0; i < 4; ++i) {
            ip2long = ip2long << 8 | parseInt(ips[i]);
        }
        return ip2long;
    }

    /**
     * 获取当前时间
     *
     * @author cdf
     * @date 2021/7/26
     */
    public static String getNow() {
        DateFormat bf = new SimpleDateFormat("yyyyMMddHHmmss");
        return bf.format(new Date());
    }

    /**
     * 毫秒转时间 ms:需要转换的毫秒时间
     */
    public static Date ms2Date(Long ms) {
        Calendar c = Calendar.getInstance();
        c.setTimeInMillis(ms);
        return c.getTime();
    }

    /**
     * 日期转字符串函数 date:需要转换的日期 strFormat:转换的格式(yyyy-MM-dd HH:mm:ss)
     */
    public static String date2String(Date date, String strFormat){
        SimpleDateFormat format = new SimpleDateFormat(strFormat);

        return format.format(date);
    }

    /**
     * 获取当前web的IP
     */
    public static String getLocalIp() {
        String host;
        try {
            host = InetAddress.getLocalHost().getHostAddress();
        } catch (UnknownHostException e) {
            e.printStackTrace();
            host = "127.0.0.1";
        }
        return host;
    }

    /**
     * 将JSON转为实体对象
     *
     * @param jsonStr    json
     * @param targetType 对象类型
     * @param <T>        对象
     */
    public static <T> T json2obj(String jsonStr, Type targetType) {
        try {
            JavaType javaType = TypeFactory.defaultInstance().constructType(targetType);
            MAPPER.registerModule(new JavaTimeModule());
            MAPPER.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
            return MAPPER.readValue(jsonStr, javaType);
        } catch (IOException e) {
            throw new IllegalArgumentException("将JSON转换为对象时发生错误:" + jsonStr, e);
        }
    }

    /**
     * 将实体对象转为JSON
     *
     * @param object   实体对象
     */
    public static String obj2json(Object object) {
        try {
            MAPPER.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
            return MAPPER.writeValueAsString(object);
        } catch (IOException e) {
            throw new IllegalArgumentException("将实体对象转为JSON时发生错误:" + object, e);
        }
    }


    /**
     * 判断一个数字是否在区间内
     *
     * @param current 待判断数字
     * @param min     最小值
     * @param max     最大值
     */
    public static boolean rangeInDefined(int current, int min, int max) {
        return Math.max(min, current) == Math.min(current, max);
    }

    /**
     * 将起始日期字符串 yyyy-MM-dd  转为 yyyy-MM-dd HH:mm:ss的LocalDateTime
     */
    public static LocalDateTime beginTimeToLocalDateTime(String beginTime) {
        beginTime = beginTime + StrUtil.SPACE + "00:00:00";
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATE_TIME);
        return LocalDateTime.parse(beginTime, dateTimeFormatter);
    }

    /**
     * 将截止日期字符串 yyyy-MM-dd  转为 yyyy-MM-dd HH:mm:ss的LocalDateTime
     */
    public static LocalDateTime endTimeToLocalDateTime(String endTime) {
        endTime = endTime + StrUtil.SPACE + "23:59:59";
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATE_TIME);
        return LocalDateTime.parse(endTime, dateTimeFormatter);
    }

    /**
     * 将字符串日期转为LocalDate日期（只用于日期转换）
     */
    public static LocalDate localDateFormat(String time) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATE);
        return LocalDate.parse(time, dateTimeFormatter);
    }

    public static LocalDateTime localDateTimeFormat(String time) {
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern(DATE_TIME);
        return LocalDateTime.parse(time, dateTimeFormatter);
    }

    /**
     * 校验时间格式
     */
    public static boolean checkDateTime(String time) {
        if(StrUtil.isBlank(time)){
            throw new BusinessException(CommonResponseEnum.TIME_ERROR);
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(DATE_TIME);

        try {
            simpleDateFormat.parse(time);
        } catch (Exception e) {
            throw new BusinessException(CommonResponseEnum.TIME_ERROR);
        }

        return true;
    }

    /**
     * 校验字符串起始时间和结束时间并返回时间格式时间
     * @author cdf
     * @date 2023/8/10
     */
    public static List<LocalDateTime> checkLocalDate(String startTime,String endTime) {
        List<LocalDateTime> resultList = new ArrayList<>();
        if(StrUtil.isBlank(startTime) || StrUtil.isBlank(endTime)){
            throw new BusinessException(CommonResponseEnum.TIME_ERROR);
        }
        try {
            startTime = startTime+StrUtil.SPACE+"00:00:00";
            endTime = endTime+StrUtil.SPACE+"23:59:59";
            LocalDateTime start = LocalDateTime.parse(startTime,DateTimeFormatter.ofPattern(DATE_TIME));
            LocalDateTime end = LocalDateTime.parse(endTime,DateTimeFormatter.ofPattern(DATE_TIME));
            resultList.add(start);
            resultList.add(end);
        } catch (Exception e) {
            throw new BusinessException(CommonResponseEnum.TIME_ERROR);
        }
        return resultList;
    }




    /**
     * 用于获取对象中，前缀一样，后缀为2~50的属性值
     *
     * @param object       待操作对象
     * @param methodPrefix 方法前缀
     * @param number       方法后缀
     * @return 对象属性值
     */
    public static Float getValueByMethod(Object object, String methodPrefix, Integer number) {
        try {
            Method method = object.getClass().getMethod(methodPrefix + number);
            return (Float) method.invoke(object);
        } catch (Exception e) {
            throw new BusinessException(CommonResponseEnum.REFLECT_METHOD_EXCEPTION);
        }
    }


    /**
     * 用于获取对象中，前缀一样，后缀为2~50的属性值
     *
     * @param object       待操作对象
     * @param methodPrefix 方法前缀
     * @param number       方法后缀
     * @return 对象属性值
     */
    public static Double getValueByMethodDouble(Object object, String methodPrefix, Integer number) {
        try {
            Method method = object.getClass().getMethod(methodPrefix + number);
            return (Double) method.invoke(object);
        } catch (Exception e) {
            throw new BusinessException(CommonResponseEnum.REFLECT_METHOD_EXCEPTION);
        }
    }


    public static List<String> getStartTimeEndTime(String beginDate, String endDate) throws Exception {

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        Calendar cal = Calendar.getInstance();
        cal.setTime(sdf.parse(beginDate));
        List<String> startTimeEndTime = null;
        for (long d = cal.getTimeInMillis(); d <= sdf.parse(endDate).getTime(); d = getDplaus(cal)) {
            startTimeEndTime.add(sdf.format(d));
        }
        return startTimeEndTime;
    }

    public static long getDplaus(Calendar c) {
        c.set(Calendar.DAY_OF_MONTH, c.get(Calendar.DAY_OF_MONTH) + 1);
        return c.getTimeInMillis();
    }

    public static String comFlag(Integer comFlag) {
        switch (comFlag) {
            case 0:
                return "中断";
            case 1:
                return "正常";
            default:
                return "";
        }
    }

    public static String runFlag(Integer runFlag) {
        switch (runFlag) {
            case 0:
                return "投运";
            case 1:
                return "热备用";
            case 2:
                return "停运";
            default:
                return "";
        }
    }

    //监测点运行状态（0：投运；1：检修；2：停运；3：调试；4：退运）
    public static String lineRunFlag(Integer runFlag) {
        switch (runFlag) {
            case 0:
                return "投运";
            case 1:
                return "检修";
            case 2:
                return "停运";
            case 3:
                return "调试";
            case 4:
                return "退运";
            default:
                return "";
        }
    }

    public static Integer getRunFlag(String runFlag) {
        switch (runFlag) {
            case "投运":
                return 0;
            case "热备用":
                return 1;
            case "停运":
                return 2;
            default:
                return -1;
        }
    }
    public static Double getDefectSeverity(String defectSeverity) {
        switch (defectSeverity) {
            case "轻缺陷":
                return 0.02;
            case "较重缺陷":
                return 0.12;
            case "严重缺陷":
                return 0.42;
            default:
                return 0.00;
        }
    }

    public static String ptType(Integer ptType) {
        switch (ptType) {
            case 0:
                return "星型接线";
            case 1:
                return "三角型接线";
            case 2:
                return "开口三角型接线";
            default:
                return "";
        }
    }

    public static Integer ptTypeName(String ptType) {
        switch (ptType) {
            case "星型接线":
                return 0;
            case "三角型接线":
                return 1;
            case "开口三角型接线":
                return 2;
            default:
                return -1;
        }
    }

    /**
     * 将当前时间的秒数置为0
     *
     * @param date 时间
     */
    public static Date getSecondsAsZero(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.SECOND, 0);
        return calendar.getTime();
    }

    /**
     * 根据起始时间和截止时间返回yyyy-MM-dd的日期，
     *
     * @param startTime 起始时间
     * @param endTime   截止时间
     */
    public static List<String> getTimes(Date startTime, Date endTime) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        List<String> result = new ArrayList<>();
        Calendar start = Calendar.getInstance();
        start.setTime(startTime);
        Calendar end = Calendar.getInstance();
        end.setTime(endTime);
        end.set(end.get(Calendar.YEAR), end.get(Calendar.MONTH), end.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
        long interval = end.getTimeInMillis() - start.getTimeInMillis();
        result.add(sdf.format(start.getTime()));
        if (interval > 0) {
            int days = (int) (interval / 86400000);
            for (int i = 0; i < days; i++) {
                start.add(Calendar.DAY_OF_MONTH, 1);
                result.add(sdf.format(start.getTime()));
            }
        }
        return result;
    }

    /***
     * 将instant转为date 处理8小时误差
     * @author hongawen
     * @date 2023/7/20 15:58
     * @param instant 日期
     * @return Instant
     */
    public static Date instantToDate(Instant instant){
        return Date.from(instant.minusMillis(TimeUnit.HOURS.toMillis(8)));
    }

    /***
     * 将date转为instant 处理8小时误差
     * @author hongawen
     * @date 2023/7/20 15:58
     * @param date 日期
     * @return Instant
     */
    public static Instant dateToInstant(Date date){
        return date.toInstant().plusMillis(TimeUnit.HOURS.toMillis(8));
    }


    /**
     * 根据参数返回float的四舍五入值
     *
     * @param i     保留的位数
     * @param value float原值
     */
    public static Float floatRound(int i, float value) {
        BigDecimal bp = new BigDecimal(value);
        return bp.setScale(i, RoundingMode.HALF_UP).floatValue();
    }

    /**
     * 根据参数返回double的四舍五入值
     *
     * @param i     保留的位数
     * @param value double原值
     */
    public static double doubleRound(int i, double value) {
        BigDecimal bp = new BigDecimal(value);
        return bp.setScale(i, RoundingMode.HALF_UP).doubleValue();
    }

    //*****************************************xuyang添加,用于App********************************************************
    /**
     * 正则表达式字符串
     * 要匹配的字符串
     *
     * @return 如果str 符合 regex的正则表达式格式,返回true, 否则返回 false;
     */
    public static boolean match(String regex, String str) {
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(str);
        return matcher.matches();
    }

    /**
     * 生成随机推荐码
     */
    public static String getCode(Integer number){
        final String BASIC = "123456789AaBbCcDdEeFfGgHhIiJjKkLlMmNnOoPpQqRrSsTtUuVvWwXxYyZz";
        char[] basicArray = BASIC.toCharArray();
        Random random = new Random();
        char[] result = new char[number];
        for (int i = 0; i < result.length; i++) {
            int index = random.nextInt(100) % (basicArray.length);
            result[i] = basicArray[index];
        }
        return new String(result);
    }

    /**
     * 将字节数组转成Float数组
     * @param bytes
     * @return
     */
    public static List<Float> byteArrayToFloatList(byte[] bytes){
        List<Float> d = new ArrayList<>(bytes.length/8);
        byte[] doubleBuffer = new byte[4];
        for(int j = 0; j < bytes.length; j += 4) {
            System.arraycopy(bytes, j, doubleBuffer, 0, doubleBuffer.length);
            d.add(bytes2Float(doubleBuffer));
        }
        return d;
    }

    public static float bytes2Float(byte[] arr) {
        int accum = 0;
        accum = accum|(arr[0] & 0xff);
        accum = accum|(arr[1] & 0xff) << 8;
        accum = accum|(arr[2] & 0xff) << 16;
        accum = accum|(arr[3] & 0xff) << 24;
        return Float.intBitsToFloat(accum);
    }

    /**
     * 将字节数组转成Double数组
     * @param arr
     * @return
     */
    public static List<Double> byteArrayToDoubleList(byte[] arr){
        List<Double> d = new ArrayList<>(arr.length/8);
        byte[] doubleBuffer = new byte[8];
        for(int j = 0; j < arr.length; j += 8) {
            System.arraycopy(arr, j, doubleBuffer, 0, doubleBuffer.length);
            d.add(bytes2Double(doubleBuffer));
        }
        return d;
    }

    /**
     * 将byte转换成double
     * @param arr
     * @return
     */
    public static double bytes2Double(byte[] arr) {
        long value = 0;
        for (int i = 0; i < 8; i++) {
            value |= ((long) (arr[i] & 0xff)) << (8 * i);
        }
        return Double.longBitsToDouble(value);
    }
    //***************************************************添加结束********************************************************
}
