package cn.cecep.talroad.vo.effective;
/*
*@Author: liuwenshuang
*@date:   2019/7/18
*/


import cn.cecep.talroad.util.effective.AirQualityLevelType;
import cn.cecep.talroad.util.effective.FieldCache;
import cn.cecep.talroad.util.effective.PollutantConcType;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.Map;

@Component
public class AirQualityConverter {
    //小时值
    public static final  Integer[][]aqiLevel = {{0, 50}, {51, 100}, {101, 150}, {151, 200}, {201, 300}, {301, 1000}};
    public static final  Integer[][]pm25Level = {{0, 35}, {36, 75}, {76, 115}, {116, 150}, {151, 250}, {251, 10000}};
    public static final  Integer[][]pm10Level = {{0, 50}, {51, 150}, {151, 250}, {251, 350}, {351, 420}, {421, 1000}};
    public static final  Integer[][]coLevel = {{0, 500}, {600, 1000}, {1100, 3500}, {3600, 6000}, {6100, 9000}, {9100, 100000}};
    public static final  Integer[][]no2Level = {{0, 100}, {101, 200}, {201, 700}, {701, 1200}, {1201, 2340}, {2341, 30000}};
    public static final  Integer[][]so2Level = {{0, 150}, {151, 500}, {501, 650}, {651, 800}, {801, 1600}, {1601, 20000}};
    public static final  Integer[][]o3Level = {{0, 160}, {161, 200}, {201, 300}, {301, 400}, {401, 800}, {801, 10000}};
    public static final  Integer[][]tspLevel = {{0, 100}, {101, 160}, {161, 215}, {216, 265}, {266, 800}, {801, 1000}};
    public static final  Integer[][]tvocLevel = {{0, 100}, {101, 160}, {161, 215}, {216, 265}, {266, 800}, {801, 1000}};
    public static final  Integer[][]noxLevel = {{0, 100}, {101, 160}, {161, 215}, {216, 265}, {266, 800}, {801, 1000}};
    public static final  Integer[][]o38hLevel = {{0, 100}, {101, 160}, {161, 215}, {216, 265}, {266, 800}, {801, 1000}};
    public static final  Integer[][]pmiLevel = {{0, 50}, {51, 100}, {101, 150}, {151, 200}, {201, 300}, {301, 1000}};
    //24h值
    public static final Integer[][] so2Level_24 = {{0,50},{51,150},{151,475},{476,800},{801,1600},{1601,2100},{2101,2620}};
    public static final Integer[][] no2level_24 = {{0,40},{41,80},{81,180},{181,280},{281,565},{566,750},{751,940}};
    public static final Integer[][] coLevel_24 = {{0,20},{30,40},{50,140},{150,240},{250,360},{370,480},{490,600}};
    public static final Integer[][] coLevel_24YYY = {{0,2},{3,4},{5,14},{15,24},{25,36},{37,48},{49,60}};
    public static final String[] airLevel = { "优", "良", "轻度污染", "中度污染", "重度污染", "严重污染" };
    public static final String[] airLevelSimple = { "优", "良", "轻度", "中度", "重度", "严重" };
    public static final String[] airLevelColor = { "43CE16", "EFDC31", "FF7E00", "FF0000", "99004C", "7E0023" };
    private static AirQualityConverter utils;
    @Autowired
    private FieldCache fieldCache;

    public static AirQualityLevelType levelNumToAQLevel(int level)
    {
        if ((level < 1) || (level > AirQualityLevelType.values().length)) {
            return null;
        }
        return AirQualityLevelType.values()[(level - 1)];
    }

    public static int ConcToIAQI(PollutantConcType pct, int iConc)
    {
        return pct.getIAQIByConc(iConc);
    }

    public static int IAQIToConc(PollutantConcType pct, int iIAQI)
    {
        return pct.getConcByIAQI(iIAQI);
    }

    public static AirQualityLevelType IAQIToAQLevel(int iIAQI)
    {
        int iAQLevelFigure = PollutantConcType.getAQLevelFigureByIAQI(iIAQI);
        if (iAQLevelFigure < 1) {
            return null;
        }
        return AirQualityLevelType.values()[(iAQLevelFigure - 1)];
    }

    // 计算AQI
    public static int concAQI(Map<String, Integer> iaqiParam) {

        int max=0;
        if(iaqiParam != null && iaqiParam.size () > 0) {
            for(Map.Entry entry : iaqiParam.entrySet()){
                if((int)entry.getValue()>max){
                    max = (int) entry.getValue();
                }
            }
        }
        return max;
    }

    // 计算PMI
    public static BigDecimal concPMI(Map<String, BigDecimal> iaqiParam) {

        BigDecimal max = new BigDecimal (0);
        if(iaqiParam != null && iaqiParam.size () > 0) {
            for(Map.Entry entry: iaqiParam.entrySet()){
                if(entry==null||entry.getValue()==null){
                    continue;
                }
                if(((BigDecimal)entry.getValue()).compareTo (max) == 1){
                    max = (BigDecimal)entry.getValue();
                }
            }
        }
        return max;
    }

    public static String concMainPollutant(Map<String, Integer> iaqiParam) {

        if(iaqiParam.size () <= 0) {
            return null;
        } else {
            int max=0;
            String key = "";
            for(Map.Entry entry: iaqiParam.entrySet()){
                if((int)entry.getValue()>max){
                    max = (int) entry.getValue();
                    key = (String) entry.getKey();
                }
            }
            return key;
        }
    }

    /**
     * 计算综合指数
     * @param pct
     * @param iConc
     * @return
     */
    public static BigDecimal concToIPMI(PollutantConcType pct, BigDecimal iConc) {
        return pct.getIPMIByConc (iConc);
    }

    public static int getIsOverByStandardHour(PollutantConcType pct, int iaqi) {
        return pct.getIsOverByStandardHour (iaqi);
    }

    /**
     * 根据六参数计算AQI
     * @param
     * @return
     */
    //24小时平均
    public static int concAqiBySixParam(BigDecimal pm25, BigDecimal pm10, BigDecimal so2, BigDecimal no2,  BigDecimal co, BigDecimal o3) {
        int pm25IAQI = PollutantConcType.PM25_24.getIAQIByConc(pm25.intValue());
        int pm10IAQI = PollutantConcType.PM10_24.getIAQIByConc(pm10.intValue());
        int so2IAQI = PollutantConcType.SO2_24.getIAQIByConc(so2.intValue());
        int no2IAQI = PollutantConcType.NO2_24.getIAQIByConc(no2.intValue());
        int coIAQI = PollutantConcType.CO_24.getIAQIByConc(co.multiply(new BigDecimal("1000")).intValue());
        int o3IAQI = PollutantConcType.O3_1.getIAQIByConc(o3.intValue());
        int[] array = {pm25IAQI, pm10IAQI, so2IAQI, no2IAQI, coIAQI, o3IAQI};
        return Arrays.stream(array).max().getAsInt();
    }

    //自定义时间计算平均，日数据
    public static int concAqiBySixParamByCustomTime(BigDecimal pm25, BigDecimal pm10, BigDecimal so2, BigDecimal no2,  BigDecimal co, BigDecimal o3) {
        int pm25IAQI = PollutantConcType.PM25_24.getIAQIByConc(pm25.intValue());
        int pm10IAQI = PollutantConcType.PM10_24.getIAQIByConc(pm10.intValue());
        int so2IAQI = PollutantConcType.SO2_24.getIAQIByConc(so2.intValue());
        int no2IAQI = PollutantConcType.NO2_24.getIAQIByConc(no2.intValue());
        int coIAQI = PollutantConcType.CO_24.getIAQIByConc(co.multiply(new BigDecimal("1000")).intValue());
        int o3IAQI = PollutantConcType.O3_8.getIAQIByConc(o3.intValue());
        int[] array = {pm25IAQI, pm10IAQI, so2IAQI, no2IAQI, coIAQI, o3IAQI};
        return Arrays.stream(array).max().getAsInt();
    }

    /**
     * 根据七参数计算AQI
     * @param
     * @return
     */
    //1小时平均
    public static int concAqiBySevenParam(BigDecimal pm25, BigDecimal pm10, BigDecimal so2, BigDecimal no2,  BigDecimal co, BigDecimal o3,BigDecimal o38h) {
        int pm25IAQI = PollutantConcType.PM25_24.getIAQIByConc(pm25.intValue());
        int pm10IAQI = PollutantConcType.PM10_24.getIAQIByConc(pm10.intValue());
        int so2IAQI = PollutantConcType.SO2_1.getIAQIByConc(so2.intValue());
        int no2IAQI = PollutantConcType.NO2_1.getIAQIByConc(no2.intValue());
        int coIAQI = PollutantConcType.CO_1.getIAQIByConc(co.multiply(new BigDecimal("1000")).intValue());
        int o3IAQI = PollutantConcType.O3_1.getIAQIByConc(o3.intValue());
        int o38hIAQI = PollutantConcType.O3_8.getIAQIByConc(o38h.intValue());
        int[] array = {pm25IAQI, pm10IAQI, so2IAQI, no2IAQI, coIAQI, o3IAQI,o38hIAQI};
        return Arrays.stream(array).max().getAsInt();
    }

    //1小时平均
    public static int concAqiBySixParam2(int pm25, int pm10, int so2, int no2,  int co, int o3) {
        int pm25IAQI = PollutantConcType.PM25_24.getIAQIByConc(pm25);
        int pm10IAQI = PollutantConcType.PM10_24.getIAQIByConc(pm10);
        int so2IAQI = PollutantConcType.SO2_1.getIAQIByConc(so2);
        int no2IAQI = PollutantConcType.NO2_1.getIAQIByConc(no2);
        int coIAQI = PollutantConcType.CO_1.getIAQIByConc(co*1000);
        int o3IAQI = PollutantConcType.O3_1.getIAQIByConc(o3);
        int[] array = {pm25IAQI, pm10IAQI, so2IAQI, no2IAQI, coIAQI, o3IAQI};
        return Arrays.stream(array).max().getAsInt();
    }

    public static BigDecimal concPMIBySixParam(BigDecimal pm25, BigDecimal pm10, BigDecimal so2, BigDecimal no2, BigDecimal co, BigDecimal o3) {
        BigDecimal pmi =  new BigDecimal(0);
        pmi = pmi.add(PollutantConcType.PM25_HOUR.getIPMIByConc(pm25));
        pmi = pmi.add(PollutantConcType.PM10_HOUR.getIPMIByConc(pm10));
        pmi = pmi.add(PollutantConcType.SO2_HOUR.getIPMIByConc(so2));
        pmi = pmi.add(PollutantConcType.NO2_HOUR.getIPMIByConc(no2));
        pmi = pmi.add(PollutantConcType.CO_HOUR.getIPMIByConc(co));
        pmi = pmi.add(PollutantConcType.O3_HOUR.getIPMIByConc(o3));
        return pmi;
    }

    /**
     * 百分位 计算方法
     *
     * @param data
     * @param p
     * @return
     */
    public static BigDecimal percentile(Object[] data, BigDecimal p) {
        BigDecimal n = new BigDecimal(data.length);
        Arrays.sort(data);
        BigDecimal px = p.multiply(n.subtract(new BigDecimal(1)));
        int i = (int) Math.floor(px.doubleValue());
        BigDecimal g = px.subtract(new BigDecimal(i));
        if (g.compareTo(new BigDecimal(0)) == 0) {
            return (BigDecimal) data[i];
        } else {
            BigDecimal data1 = (BigDecimal) data[i];
            BigDecimal data2 = (BigDecimal) data[i + 1];
            BigDecimal value = (new BigDecimal(1).subtract(g)).multiply(data1).add(g.multiply(data2));
            return value;
        }
    }

    /**
     * 根据因子判断等级 (优 良)
     * @param pollutant 污染物名称 pm25
     * @param val   污染值  1.11
     * @param type  返回数组类型  1:全称  2:简称
     * @param is24 是否用24小时的
     * @return
     */
    public static String airQualityLevel(String pollutant,BigDecimal val,Integer type,boolean is24){
        if(StringUtils.isNotBlank(pollutant)){
            if((is24==true && "o3".equals(pollutant)) || "o3_8h".equals(pollutant)){
                pollutant = "o38h";
            }
            if(ObjectUtils.isNotEmpty(val)){
                //co*10好判断
                if("co".equals(pollutant)){
                    val = val.multiply(new BigDecimal(10));
                }
                AirQualityLevelVo qualityLevelVo = new AirQualityLevelVo();
                String propertyName = pollutant.concat("Level");
                //只有这三个有24小时区间
                if("so2".equals(pollutant) || "no2".equals(pollutant) || "co".equals(pollutant)){
                    propertyName = is24 ? propertyName.concat("24") : pollutant.concat("Level");
                }
                //通过因子名称获取对应的区间数组
                Integer[][] poLevel = (Integer[][]) utils.fieldCache.get(qualityLevelVo, propertyName);
                if(ArrayUtils.isNotEmpty(poLevel)){
                    for (int i = 0; i < poLevel.length; i++) {
                        if(val.compareTo(new BigDecimal(poLevel[i][0])) > -1 && val.compareTo(new BigDecimal(poLevel[i][1])) < 1){
                            String levelStr = type == 1 ? airLevel[i] : airLevelSimple[i];
                            return levelStr;
                        }
                    }
                }
            }
        }
        return "--";
    }

    /**
     *
     * @param pollutant     污染物名称
     * @param val           值
     * @param is24          是否使用24小时限值  天true 小时 false
     * @return
     */
    public static Integer airQualityLevelNumber(String pollutant,BigDecimal val,boolean is24){
        if(StringUtils.isNotBlank(pollutant)){
            if((is24==true && "o3".equals(pollutant)) || "o3_8h".equals(pollutant)){
                pollutant = "o38h";
            }
            if(ObjectUtils.isNotEmpty(val)){
                //co*10好判断
                if("co".equals(pollutant)){
                    val = val.multiply(new BigDecimal(10));
                }
                AirQualityLevelVo qualityLevelVo = new AirQualityLevelVo();
                String propertyName = pollutant.concat("Level");
                //只有这三个有24小时区间
                if("so2".equals(pollutant) || "no2".equals(pollutant) || "co".equals(pollutant)){
                    pollutant = is24 ? pollutant.concat("_24") : pollutant;
                }
                //通过因子名称获取对应的区间数组
                Integer[][] poLevel = (Integer[][]) utils.fieldCache.get(qualityLevelVo, propertyName);
                if(ArrayUtils.isNotEmpty(poLevel)){
                    for (int i = 0; i < poLevel.length; i++) {
                        if(val.compareTo(new BigDecimal(poLevel[i][0])) > -1 && val.compareTo(new BigDecimal(poLevel[i][1])) < 1){
                            return i + 1;
                        }
                    }
                }
            }
        }
        return null;
    }

    public static String airQualityLevelColor(String airLevelStr,Integer type){
        String nullValueStr = "--";
        if(StringUtils.isNotBlank(airLevelStr) && !nullValueStr.equals(airLevelStr)){
            for (int i = 0; i < airLevel.length; i++) {
                if(airLevelStr.equals(type == 1  ? airLevel[i] : airLevelSimple[i])){
                    return airLevelColor[i];
                }
            }
        }
        return "";
    }

    @PostConstruct
    public void init(){
        utils = this;
        System.out.println("执行大气操作=======》");
    }

}
