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

import java.math.BigDecimal;

public enum PollutantConcType {
    CO_HOUR(0), NO2_HOUR(1), O3_HOUR(2), SO2_HOUR(3), PM10_HOUR(4), PM25_HOUR(5),
    CO_1(0),  CO_24(1),  NO2_1(2),  NO2_24(3),  O3_1(4),  O3_8(5),  SO2_1(6),  SO2_24(7),  PM25_24(8),  PM10_24(9),  CO_8(10);

    private static final int[] m_aiIAQIScopeForLevel = { 0, 50, 100, 150, 200, 300 };
    private static final int[] m_aiIAQIScope = { 0, 50, 100, 150, 200, 300, 400, 500 };
    // 环境空气污染物基本项目浓度限值二级标准
    private static final int[] m_aiPMIStandardHour = { 4, 40, 160, 60, 70, 35 };
    private static final int[][] m_aiConcScope = {
            { 0, 5000, 10000, 35000, 60000, 90000, 120000, 150000 },
            { 0, 2000, 4000, 14000, 24000, 36000, 48000, 60000 },
            { 0, 100, 200, 700, 1200, 2340, 3090, 3840 },
            { 0, 40, 80, 180, 280, 565, 750, 940 },
            { 0, 160, 200, 300, 400, 800, 1000, 1200 },
            { 0, 100, 160, 215, 265, 800, -1, -1 },
            { 0, 150, 500, 650, 800, -1, -1, -1 },
            { 0, 50, 150, 475, 800, 1600, 2100, 2620 },
            { 0, 35, 75, 115, 150, 250, 350, 500 },
            { 0, 50, 150, 250, 350, 420, 500, 600 },
            { 0, -1, -1, -1, -1, -1, -1, -1 } };
    private final int m_iIdx;

    private PollutantConcType(int value)
    {
        this.m_iIdx = value;
    }

    private static int getAQLevelFigure(int[] aiIAQIScopeForLevel, int iIAQI)
    {
        if (iIAQI < 0) {
            return -1;
        }
        if (iIAQI == 0) {
            return 1;
        }
        int iScopeIdx = -1;
        for (int i = 0; i < aiIAQIScopeForLevel.length - 1; i++) {
            if ((iIAQI > aiIAQIScopeForLevel[i]) && (iIAQI <= aiIAQIScopeForLevel[(i + 1)]))
            {
                iScopeIdx = i;
                break;
            }
        }
        if (iScopeIdx < 0) {
            iScopeIdx = 5;
        }
        return iScopeIdx + 1;
    }

    public static int getAQLevelFigureByIAQI(int iIAQI)
    {
        return getAQLevelFigure(m_aiIAQIScopeForLevel, iIAQI);
    }

    private int getIAQI(int[] aiIAQIScope, int[][] aiConcScope, int iConc)
    {
        if (iConc < 0) {
            return -1;
        }
        int iScopeIdx = -1;
        boolean bValid = true;
        for (int i = 0; i < aiConcScope[this.m_iIdx].length - 1; i++)
        {
            if (aiConcScope[this.m_iIdx][(i + 1)] < 0) {
                break;
            }
            if ((iConc >= aiConcScope[this.m_iIdx][i]) && (iConc <= aiConcScope[this.m_iIdx][(i + 1)]))
            {
                if (aiConcScope[this.m_iIdx][i] < 0)
                {
                    bValid = false;
                    break;
                }
                iScopeIdx = i;
                break;
            }
        }
        if (!bValid) {
            return -1;
        }
        if (iScopeIdx < 0) {
            return getIAQIMaxVal(aiIAQIScope, aiConcScope);
        }
        int[] aiCScope = aiConcScope[this.m_iIdx];
        BigDecimal ia = new BigDecimal((iConc - aiCScope[iScopeIdx]) * (aiIAQIScope[(iScopeIdx + 1)] - aiIAQIScope[iScopeIdx]));
        BigDecimal ib =new BigDecimal(aiCScope[(iScopeIdx + 1)] - aiCScope[iScopeIdx]);

        return ia.divide(ib,0,BigDecimal.ROUND_HALF_EVEN).intValue() + aiIAQIScope[iScopeIdx];
    }

    private BigDecimal getPollutantValueByIAQI(int[] aiIAQIScope, int[][] aiConcScope, int iConc)
    {
        if (iConc < 0) {
            return new BigDecimal(-1);
        }
        int iScopeIdx = -1;
        boolean bValid = true;
        for (int i = 0; i < aiIAQIScope.length - 1; i++)
        {
            if ((iConc >= aiIAQIScope[i]) && (iConc <= aiIAQIScope[(i + 1)]))
            {
                if (aiConcScope[this.m_iIdx][i] < 0)
                {
                    bValid = false;
                    break;
                }
                iScopeIdx = i;
                break;
            }
        }
        if (!bValid) {
            return new BigDecimal(-1);
        }

        int[] aiCScope = aiConcScope[this.m_iIdx];
        BigDecimal ia = new BigDecimal((iConc - aiIAQIScope[iScopeIdx]) * (aiCScope[(iScopeIdx + 1)] - aiCScope[iScopeIdx]));
        BigDecimal ib =new BigDecimal(aiIAQIScope[(iScopeIdx + 1)] - aiIAQIScope[iScopeIdx]);

        return ia.divide(ib,0,BigDecimal.ROUND_HALF_EVEN).add(new BigDecimal(aiCScope[iScopeIdx]));
    }

    private BigDecimal getIPMI(int[] m_aiPMIStandardHour, BigDecimal iConc) {
        if (iConc.compareTo (new BigDecimal (0)) == -1) {
            return new BigDecimal (-1);
        }
        int value = m_aiPMIStandardHour[this.m_iIdx];
        return iConc.divide (new BigDecimal (value), 2, BigDecimal.ROUND_HALF_EVEN);
    }

    private int getConc(int[] aiIAQIScope, int[][] aiConcScope, int iIAQI)
    {
        if (iIAQI < 0) {
            return -1;
        }
        int iIAQI2 = iIAQI;
        int iIAQIMax = getIAQIMaxVal(aiIAQIScope, aiConcScope);
        if (iIAQIMax < 0) {
            return -1;
        }
        if (iIAQI2 > iIAQIMax) {
            iIAQI2 = iIAQIMax;
        }
        int iScopeIdx = -1;
        for (int i = 0; i < aiIAQIScope.length - 1; i++) {
            if ((iIAQI2 >= aiIAQIScope[i]) && (iIAQI2 <= aiIAQIScope[(i + 1)]))
            {
                iScopeIdx = i;
                break;
            }
        }
        if (iScopeIdx < 0) {
            return -1;
        }
        int[] aiCScope = aiConcScope[this.m_iIdx];
        if ((aiCScope[iScopeIdx] < 0) || (aiCScope[(iScopeIdx + 1)] < 0)) {
            return -1;
        }
        int ia = (iIAQI2 - aiIAQIScope[iScopeIdx]) * (aiCScope[(iScopeIdx + 1)] - aiCScope[iScopeIdx]);
        int ib = aiIAQIScope[(iScopeIdx + 1)] - aiIAQIScope[iScopeIdx];
        return (int)Math.round(ia / ib) + aiCScope[iScopeIdx];
    }

    private int getIAQIMaxVal(int[] aiIAQIScope, int[][] aiConcScope)
    {
        int i;
        for (i = aiConcScope[this.m_iIdx].length - 1; i >= 0; i--) {
            if (aiConcScope[this.m_iIdx][i] > 0) {
                break;
            }
        }
        if (i < 0) {
            return -1;
        }
        return aiIAQIScope[i];
    }

    public int getIAQIByConc(int iConc)
    {
        return getIAQI(m_aiIAQIScope, m_aiConcScope, iConc);
    }

    public BigDecimal getPollutantValueByIAQI(int iConc)
    {
        return getPollutantValueByIAQI(m_aiIAQIScope, m_aiConcScope, iConc);
    }

    public BigDecimal getIPMIByConc(BigDecimal iConc) {
        return getIPMI(m_aiPMIStandardHour, iConc);
    }

    public int getConcByIAQI(int iIAQI)
    {
        return getConc(m_aiIAQIScope, m_aiConcScope, iIAQI);
    }

    public int getIAQIMax()
    {
        return getIAQIMaxVal(m_aiIAQIScope, m_aiConcScope);
    }

    public int getIsOverByStandardHour(int iaqi) {
        return getIsOver (m_aiPMIStandardHour, iaqi);
    }

    private int getIsOver(int[] m_aiPMIStandardHour, int iaqi) {
        if (iaqi < 0) {
            return -1;
        }
        int value = m_aiPMIStandardHour[this.m_iIdx];
        if(iaqi > value)
            return 1;
        else
            return 0;
    }
}
