package com.pqs9000.serviceimpl.responsibility;

import com.alibaba.fastjson.JSON;
import com.njcn.mapper.system.ThemeMapper;
import com.njcn.pojo.commons.AreaGeneralData;
import com.njcn.pojo.commons.RedisDB;
import com.njcn.pojo.system.Theme;
import com.njcn.pojo.user.Depts;
import com.njcn.utils.UserUtil;
import com.njcn.utils.redis.JedisManager;
import com.pqs9000.mapper.responsibility.AreaOverNormalMapper;
import com.pqs9000.pojo.responsibility.AreaOverNoraml;
import com.pqs9000.pojo.responsibility.OverLimitByDays;
import com.pqs9000.service.responsibility.AreaOverNoramlService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import java.awt.geom.Arc2D;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.*;

import javax.annotation.Resource;

/**
 * @author xuyang
 * @date 2020/9/21 14:51
 */

@Service
public class AreaOverNormalServiceImpl implements AreaOverNoramlService {

    @Autowired
    private UserUtil userUtil;

    @Autowired
    private AreaOverNormalMapper areaOverNormalMapper;

    @Autowired
    private JedisManager jedisManager;

    @Resource
    private ThemeMapper themeMapper;


    @Override
    public List<AreaOverNoraml> getOverLimitData(String startTime, String endTime,String type,int statistic,boolean statFlag, Integer monitorNature) {
        List<Integer> allMonitors = new ArrayList<>();
        List<Integer> normalMonitors = new ArrayList<>();
        List<Integer> monitor = new ArrayList<>();
        String name = "";
        String value ="";
        List<AreaOverNoraml> areaOverNoramls = new ArrayList<>();
        List<AreaOverNoraml> monitorList = new ArrayList<>();
        AreaOverNoraml areaOverNoraml;
        AreaOverNoraml avg;
        List<AreaGeneralData> ag;
        String deptsIndex = userUtil.getCurrentDept().getDeptsIndex();
        //新增统计类型判断
        if(statFlag){
            ag = userUtil.getAreaDataByInfoRun(deptsIndex);
        }else {
            //排除不需要计算的监测点
            ag =userUtil.getAreaDataByStatFlagAll(deptsIndex);
        }
        //新增电网侧\用户侧判断
        if (!Objects.isNull(monitorNature) && monitorNature != -1) {
            ag.forEach(item->{
                List<Integer> line = areaOverNormalMapper.getMonitorNature(item.getLineIndexs(),monitorNature);
                if (CollectionUtils.isEmpty(line)) {
                    item.setMonitors(0);
                    item.setLineIndexs(line);
                } else {
                    item.setMonitors(line.size());
                    item.setLineIndexs(line);
                }
            });
        }
        String typename ="";
        Theme theme = new Theme();
        theme.setState(1);
        theme.setActive(1);
        theme=themeMapper.selectOne(theme);
        if(null==theme){
        	typename = "国网";
        }else{
        	typename=theme.getThemeDesc();
        }
        for (AreaGeneralData line: ag) {
            normalMonitors.addAll(line.getLineIndexs());
        }
        //判断是不是国网(灿能)类型监测点
        if (type.equals(typename)){
            List<Integer> list = new ArrayList<>();
            for (AreaGeneralData typeDate:ag) {
                if (typeDate.getMonitors() !=0 ){
                    list = countryMonitor(typeDate.getLineIndexs());
                }
                if (list.isEmpty()){
                    typeDate.setMonitors(0);
                } else {
                    typeDate.setMonitors(list.size());
                }
                typeDate.setLineIndexs(list);
            }
        }
        //获取所有监测点
        for (AreaGeneralData line: ag) {
            allMonitors.addAll(line.getLineIndexs());
        }
        //判断所选类型
        switch (statistic){
            case 0:
                for (AreaGeneralData line: ag) {
                    areaOverNoraml = new AreaOverNoraml();
                    //判断是否有监测点
                    if (line.getMonitors() == 0){
                        areaOverNoraml.setName(line.getName());
                        computeZero(areaOverNoraml);
                        areaOverNoramls.add(areaOverNoraml);
                    } else {
                        areaOverNoraml = areaOverNormalMapper.getInfo(line.getLineIndexs(),startTime,endTime);
                        avg = areaOverNormalMapper.getAvg(line.getLineIndexs(),startTime,endTime);
                        areaOverNoraml.setName(line.getName());
                        if (!Objects.isNull(avg)){
                            areaOverNoraml.setFrequencyAvg(avg.getFrequencyAvg());
                            areaOverNoraml.setVoltageAvg(avg.getVoltageAvg());
                            areaOverNoraml.setHarmonicVoltageAvg(avg.getHarmonicVoltageAvg());
                            areaOverNoraml.setHarmonicCurrentAvg(avg.getHarmonicCurrentAvg());
                            areaOverNoraml.setThreePhaseVoltageAvg(avg.getThreePhaseVoltageAvg());
                            areaOverNoraml.setFlickerAvg(avg.getFlickerAvg());
                            areaOverNoraml.setNegativeAvg(avg.getNegativeAvg());
                            areaOverNoraml.setInterharmonicAvg(avg.getInterharmonicAvg());
                        }
                        if (areaOverNoraml.getOnlineMonitorNumber() != 0){
                            Map<String,Double> map = getPercentage(areaOverNoraml,line.getLineIndexs(),startTime,endTime);
                            compute(map,areaOverNoraml);
                        } else {
                            computeZero(areaOverNoraml);
                        }
                        areaOverNoramls.add(areaOverNoraml);
                    }
                }
                if(ag.size()>1){
                    monitorList.add(superiorObject(allMonitors,startTime,endTime));
                }
                break;
            case 1:
                if (allMonitors.isEmpty()){
                    List<Map<String,String>> typeList = areaOverNormalMapper.getTypeList(normalMonitors);
                    for (Map<String,String> m : typeList) {
                        areaOverNoraml = new AreaOverNoraml();
                        name = m.get("DIC_NAME");
                        areaOverNoraml.setName(name);
                        computeZero(areaOverNoraml);
                        areaOverNoramls.add(areaOverNoraml);
                    }
                } else {
                    List<Map<String,String>> typeList = areaOverNormalMapper.getTypeList(allMonitors);
                    for (Map<String,String> m : typeList) {
                        name = m.get("DIC_NAME");
                        value = m.get("LOADTYPE");
                        monitor = areaOverNormalMapper.getMonitorByType(allMonitors,value);
                        areaOverNoraml = areaOverNormalMapper.getInfo(monitor,startTime,endTime);
                        avg = areaOverNormalMapper.getAvg(monitor,startTime,endTime);
                        areaOverNoraml.setName(name);
                        if (!Objects.isNull(avg)){
                            areaOverNoraml.setFrequencyAvg(avg.getFrequencyAvg());
                            areaOverNoraml.setVoltageAvg(avg.getVoltageAvg());
                            areaOverNoraml.setHarmonicVoltageAvg(avg.getHarmonicVoltageAvg());
                            areaOverNoraml.setHarmonicCurrentAvg(avg.getHarmonicCurrentAvg());
                            areaOverNoraml.setThreePhaseVoltageAvg(avg.getThreePhaseVoltageAvg());
                            areaOverNoraml.setFlickerAvg(avg.getFlickerAvg());
                            areaOverNoraml.setNegativeAvg(avg.getNegativeAvg());
                            areaOverNoraml.setInterharmonicAvg(avg.getInterharmonicAvg());
                        }
                        if (areaOverNoraml.getOnlineMonitorNumber() != 0){
                            Map<String,Double> map = getPercentage(areaOverNoraml,monitor,startTime,endTime);
                            compute(map,areaOverNoraml);
                        } else {
                            computeZero(areaOverNoraml);
                        }
                        areaOverNoramls.add(areaOverNoraml);
                    }
                }
                break;
            case 2:
                if (allMonitors.isEmpty()){
                    List<Map<String,String>> volList = areaOverNormalMapper.getVolList(normalMonitors);
                    for (Map<String,String> m : volList) {
                        areaOverNoraml = new AreaOverNoraml();
                        name = m.get("DIC_NAME");
                        areaOverNoraml.setName(name);
                        computeZero(areaOverNoraml);
                        areaOverNoramls.add(areaOverNoraml);
                    }
                } else {
                    List<Map<String,String>> volList = areaOverNormalMapper.getVolList(allMonitors);
                    for (Map<String,String> m : volList) {
                        name = m.get("DIC_NAME");
                        value = m.get("SCALE");
                        monitor = areaOverNormalMapper.getMonitorByVol(allMonitors,value);
                        areaOverNoraml = areaOverNormalMapper.getInfo(monitor,startTime,endTime);
                        avg = areaOverNormalMapper.getAvg(monitor,startTime,endTime);
                        areaOverNoraml.setName(name);
                        if (!Objects.isNull(avg)){
                            areaOverNoraml.setFrequencyAvg(avg.getFrequencyAvg());
                            areaOverNoraml.setVoltageAvg(avg.getVoltageAvg());
                            areaOverNoraml.setHarmonicVoltageAvg(avg.getHarmonicVoltageAvg());
                            areaOverNoraml.setHarmonicCurrentAvg(avg.getHarmonicCurrentAvg());
                            areaOverNoraml.setThreePhaseVoltageAvg(avg.getThreePhaseVoltageAvg());
                            areaOverNoraml.setFlickerAvg(avg.getFlickerAvg());
                            areaOverNoraml.setNegativeAvg(avg.getNegativeAvg());
                            areaOverNoraml.setInterharmonicAvg(avg.getInterharmonicAvg());
                        }
                        if (areaOverNoraml.getOnlineMonitorNumber() != 0){
                            Map<String,Double> map = getPercentage(areaOverNoraml,monitor,startTime,endTime);
                            compute(map,areaOverNoraml);
                        } else {
                            computeZero(areaOverNoraml);
                        }
                        areaOverNoramls.add(areaOverNoraml);
                    }
                }
                break;
            default:
                break;
        }
        monitorList.addAll(areaOverNoramls);
        //处理数据存入redis，用于导出报表
        String json = JSON.toJSONString(monitorList);
        jedisManager.saveValueByKey(RedisDB.REPORTID,RedisDB.AREAREPORTNAME,json,3600);
        return monitorList;
    }


    //保留两位小数
    private Double saveTwoNumber(double num){
        DecimalFormat df = new DecimalFormat("0.00");
        return Double.parseDouble(df.format(num));
    }

    //获取国网监测点
    public List<Integer> countryMonitor(List<Integer> list){
        return areaOverNormalMapper.getCountryMonitor(list);
    }


    //根据用户获取所属部门名称，用于总计使用
    private String getDeptName(){
        Depts dep = userUtil.getCurrentDept();
        String deptName = dep.getArea();
        return deptName;
    }

    /**
     *  获取每天在线监测点、超标监测点、超标次数、当月每天时间
     */
    private Map<String,Double> getPercentage(AreaOverNoraml areaOverNoraml,List<Integer> list, String startTime, String endTime){
        Map<String,Double> map = new HashMap<>();
        BigDecimal bg = null;

        List<OverLimitByDays> frequencyList = areaOverNormalMapper.getFrequency(list,startTime,endTime);
//        double frequencyCompliance = getComplianceRatio(frequencyList);
        bg = BigDecimal.valueOf(areaOverNoraml.getFrequencyMonitorNumber() * 1.0 / areaOverNoraml.getOnlineMonitorNumber() * 100);
        double frequencyCompliance = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        Map<String,Double> frequencyMap = handleResult(areaOverNoraml.getFrequencyMonitorNumber(),frequencyList);

        List<OverLimitByDays> voltageList = areaOverNormalMapper.getVoltage(list,startTime,endTime);
//        double voltageCompliance = getComplianceRatio(voltageList);
        bg = BigDecimal.valueOf(areaOverNoraml.getVoltageMonitorNumber() * 1.0 / areaOverNoraml.getOnlineMonitorNumber() * 100);
        double voltageCompliance = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        Map<String,Double> voltageMap = handleResult(areaOverNoraml.getVoltageMonitorNumber(),voltageList);

        List<OverLimitByDays> harmonicVoltageList = areaOverNormalMapper.getHarmonicVoltage(list,startTime,endTime);
//        double harmonicVoltageCompliance = getComplianceRatio(harmonicVoltageList);
        bg = BigDecimal.valueOf(areaOverNoraml.getHarmonicVoltageMonitorNumber() * 1.0 / areaOverNoraml.getOnlineMonitorNumber() * 100);
        double harmonicVoltageCompliance = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        Map<String,Double> harmonicVoltageMap = handleResult(areaOverNoraml.getHarmonicVoltageMonitorNumber(),harmonicVoltageList);

        List<OverLimitByDays> harmonicCurrentList = areaOverNormalMapper.getHarmonicCurrent(list,startTime,endTime);
//        double harmonicCurrentCompliance = getComplianceRatio(harmonicCurrentList);
        bg = BigDecimal.valueOf(areaOverNoraml.getHarmonicCurrentMonitorNumber() * 1.0 / areaOverNoraml.getOnlineMonitorNumber() * 100);
        double harmonicCurrentCompliance = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        Map<String,Double> harmonicCurrentMap = handleResult(areaOverNoraml.getHarmonicCurrentMonitorNumber(),harmonicCurrentList);

        List<OverLimitByDays> threePhaseVoltageList = areaOverNormalMapper.getThreePhaseVoltage(list,startTime,endTime);
//        double threePhaseVoltageCompliance = getComplianceRatio(threePhaseVoltageList);
        bg = BigDecimal.valueOf(areaOverNoraml.getThreePhaseVoltageMonitorNumber() * 1.0 / areaOverNoraml.getOnlineMonitorNumber() * 100);
        double threePhaseVoltageCompliance = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        Map<String,Double> threePhaseVoltageMap = handleResult(areaOverNoraml.getThreePhaseVoltageMonitorNumber(),threePhaseVoltageList);

        List<OverLimitByDays> flickerList = areaOverNormalMapper.getFlicker(list,startTime,endTime);
//        double flickerCompliance = getComplianceRatio(flickerList);
        bg = BigDecimal.valueOf(areaOverNoraml.getFlickerMonitorNumber() * 1.0 / areaOverNoraml.getOnlineMonitorNumber() * 100);
        double flickerCompliance = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        Map<String,Double> flickerMap = handleResult(areaOverNoraml.getFlickerMonitorNumber(),flickerList);

        List<OverLimitByDays> negativeList = areaOverNormalMapper.getNegative(list,startTime,endTime);
//        double negativeCompliance = getComplianceRatio(negativeList);
        bg = BigDecimal.valueOf(areaOverNoraml.getNegativeMonitorNumber() * 1.0 / areaOverNoraml.getOnlineMonitorNumber() * 100);
        double negativeCompliance = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        Map<String,Double> negativeMap = handleResult(areaOverNoraml.getNegativeMonitorNumber(),negativeList);

        List<OverLimitByDays> interharmonicList = areaOverNormalMapper.getInterharmonic(list,startTime,endTime);
//        double interharmonicCompliance = getComplianceRatio(interharmonicList);
        bg = BigDecimal.valueOf(areaOverNoraml.getInterharmonicMonitorNumber() * 1.0 / areaOverNoraml.getOnlineMonitorNumber() * 100);
        double interharmonicCompliance = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        Map<String,Double> interharmonicMap = handleResult(areaOverNoraml.getInterharmonicMonitorNumber(),interharmonicList);

        map.put("frequencyOverDayBiLi",frequencyMap.get("overAverageDaysAvg"));
        map.put("voltageOverDayBiLi",voltageMap.get("overAverageDaysAvg"));
        map.put("harmonicVoltageOverDayBiLi",harmonicVoltageMap.get("overAverageDaysAvg"));
        map.put("harmonicCurrentOverDayBiLi",harmonicCurrentMap.get("overAverageDaysAvg"));
        map.put("threePhaseVoltageOverDayBiLi",threePhaseVoltageMap.get("overAverageDaysAvg"));
        map.put("flickerOverDayBiLi",flickerMap.get("overAverageDaysAvg"));
        map.put("negativeOverDayBiLi",negativeMap.get("overAverageDaysAvg"));
        map.put("interharmonicOverDayBiLi",interharmonicMap.get("overAverageDaysAvg"));
        //符合性占比统计
        map.put("frequencyBiLi",frequencyCompliance);
        map.put("voltageBiLi",voltageCompliance);
        map.put("harmonicVoltageBiLi",harmonicVoltageCompliance);
        map.put("harmonicCurrentBiLi",harmonicCurrentCompliance);
        map.put("threePhaseVoltageBiLi",threePhaseVoltageCompliance);
        map.put("flickerBiLi",flickerCompliance);
        map.put("negativeBiLi",negativeCompliance);
        map.put("interharmonicBiLi",interharmonicCompliance);
        return map;
    }

    //计算符合性占比统计
    public double getComplianceRatio(List<OverLimitByDays> list){
        double number = 0.0;
        double result = 0.0;
        BigDecimal bg = null;
        if (!list.isEmpty()){
            for (OverLimitByDays pojo:list) {
                if (pojo.getOverCounts() != 0){
                    number = number + pojo.getOverTotal()/(pojo.getOverCounts()*1.0);
                }
            }
            bg = new BigDecimal(number/list.size()*100);
            result = bg.setScale(2, BigDecimal.ROUND_HALF_UP).doubleValue();
        }
        return  result;
    }

    //处理结果集，获取到比例
    private Map<String,Double> handleResult(int total,List<OverLimitByDays> list){
        Map<String,Double> map = new HashMap<>();
        if (list.isEmpty()){
            map.put("overAverageDaysAvg",saveTwoNumber(0));
        } else {
            double overAverageDays = 0.0;
            int counts = 0;
            for (OverLimitByDays overLimitByDays:list) {
                if (overLimitByDays.getOverTotal() == 0){
                    counts = counts + 0;
                } else {
                    counts = counts + overLimitByDays.getOverTotal();
                }
            }
            if (total == 0){
                overAverageDays = 0;
            }else {
                overAverageDays = (double)counts/total;
            }
            map.put("overAverageDaysAvg",saveTwoNumber(overAverageDays));
        }
        return map;
    }


    //获取上级部门所有监测点
    private AreaOverNoraml superiorObject(List<Integer> list,String startTime,String endTime){
        AreaOverNoraml areaOverNoraml = new AreaOverNoraml();
        AreaOverNoraml avg = new AreaOverNoraml();
        if (list.isEmpty()){
            areaOverNoraml.setName(getDeptName());
            computeZero(areaOverNoraml);
        }else {
            areaOverNoraml = areaOverNormalMapper.getInfo(list,startTime,endTime);
            avg = areaOverNormalMapper.getAvg(list,startTime,endTime);
            areaOverNoraml.setName(getDeptName());
            if (!Objects.isNull(avg)){
                areaOverNoraml.setFrequencyAvg(avg.getFrequencyAvg());
                areaOverNoraml.setVoltageAvg(avg.getVoltageAvg());
                areaOverNoraml.setHarmonicVoltageAvg(avg.getHarmonicVoltageAvg());
                areaOverNoraml.setHarmonicCurrentAvg(avg.getHarmonicCurrentAvg());
                areaOverNoraml.setThreePhaseVoltageAvg(avg.getThreePhaseVoltageAvg());
                areaOverNoraml.setFlickerAvg(avg.getFlickerAvg());
                areaOverNoraml.setNegativeAvg(avg.getNegativeAvg());
                areaOverNoraml.setInterharmonicAvg(avg.getInterharmonicAvg());
            }
            if (areaOverNoraml.getOnlineMonitorNumber() != 0){
                Map<String,Double> map = getPercentage(areaOverNoraml,list,startTime,endTime);
                compute(map,areaOverNoraml);
            } else {
                computeZero(areaOverNoraml);
            }
        }
        return areaOverNoraml;
    }

    //计算平均超标天数
    public void compute(Map<String,Double> map,AreaOverNoraml areaOverNoraml) {
        areaOverNoraml.setFrequencyOverDayBiLi(map.get("frequencyOverDayBiLi"));
        areaOverNoraml.setVoltageOverDayBiLi(map.get("voltageOverDayBiLi"));
        areaOverNoraml.setHarmonicVoltageOverDayBiLi(map.get("harmonicVoltageOverDayBiLi"));
        areaOverNoraml.setHarmonicCurrentOverDayBiLi(map.get("harmonicCurrentOverDayBiLi"));
        areaOverNoraml.setThreePhaseVoltageOverDayBiLi(map.get("threePhaseVoltageOverDayBiLi"));
        areaOverNoraml.setFlickerOverDayBiLi(map.get("flickerOverDayBiLi"));
        areaOverNoraml.setNegativeOverDayBiLi(map.get("negativeOverDayBiLi"));
        areaOverNoraml.setInterharmonicOverDayBiLi(map.get("interharmonicOverDayBiLi"));
        //符合性统计
        areaOverNoraml.setFrequencyBiLi(map.get("frequencyBiLi"));
        areaOverNoraml.setVoltageBiLi(map.get("voltageBiLi"));
        areaOverNoraml.setHarmonicVoltageBiLi(map.get("harmonicVoltageBiLi"));
        areaOverNoraml.setHarmonicCurrentBiLi(map.get("harmonicCurrentBiLi"));
        areaOverNoraml.setThreePhaseVoltageBiLi(map.get("threePhaseVoltageBiLi"));
        areaOverNoraml.setFlickerBiLi(map.get("flickerBiLi"));
        areaOverNoraml.setNegativeBiLi(map.get("negativeBiLi"));
        areaOverNoraml.setInterharmonicBiLi(map.get("interharmonicBiLi"));
    }

    public void computeZero(AreaOverNoraml areaOverNoraml) {
        areaOverNoraml.setOnlineMonitorNumber(0);
        areaOverNoraml.setOverLimitMonitorNumber(0);

        areaOverNoraml.setFrequencyMonitorNumber(0);
        areaOverNoraml.setFrequencyBiLi(0.00);
        areaOverNoraml.setFrequencyAvg(0.00);

        areaOverNoraml.setVoltageMonitorNumber(0);
        areaOverNoraml.setVoltageBiLi(0.00);
        areaOverNoraml.setVoltageAvg(0.00);

        areaOverNoraml.setHarmonicVoltageMonitorNumber(0);
        areaOverNoraml.setHarmonicVoltageBiLi(0.00);
        areaOverNoraml.setHarmonicVoltageAvg(0.00);

        areaOverNoraml.setHarmonicCurrentMonitorNumber(0);
        areaOverNoraml.setHarmonicCurrentBiLi(0.00);
        areaOverNoraml.setHarmonicCurrentAvg(0.00);

        areaOverNoraml.setThreePhaseVoltageMonitorNumber(0);
        areaOverNoraml.setThreePhaseVoltageBiLi(0.00);
        areaOverNoraml.setThreePhaseVoltageAvg(0.00);

        areaOverNoraml.setFlickerMonitorNumber(0);
        areaOverNoraml.setFlickerBiLi(0.00);
        areaOverNoraml.setFlickerAvg(0.00);

        areaOverNoraml.setNegativeMonitorNumber(0);
        areaOverNoraml.setNegativeBiLi(0.00);
        areaOverNoraml.setNegativeAvg(0.00);

        areaOverNoraml.setInterharmonicMonitorNumber(0);
        areaOverNoraml.setInterharmonicBiLi(0.00);
        areaOverNoraml.setInterharmonicAvg(0.00);

        areaOverNoraml.setOverBiLi(0.00);
        areaOverNoraml.setFrequencyOverDayBiLi(0.00);
        areaOverNoraml.setVoltageOverDayBiLi(0.00);
        areaOverNoraml.setHarmonicVoltageOverDayBiLi(0.00);
        areaOverNoraml.setHarmonicCurrentOverDayBiLi(0.00);
        areaOverNoraml.setThreePhaseVoltageOverDayBiLi(0.00);
        areaOverNoraml.setFlickerOverDayBiLi(0.00);
        areaOverNoraml.setNegativeOverDayBiLi(0.00);
        areaOverNoraml.setInterharmonicOverDayBiLi(0.00);
    }

}
