package com.gyee.generation.util.math;

import com.gyee.common.model.PointData;
import com.gyee.common.model.StringUtils;
import com.gyee.generation.model.vo.PowerVo;
import com.gyee.generation.util.DateUtils;
import com.gyee.generation.util.realtimesource.IEdosUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;

@Service
public class LightToTheoreticalPower {
    @Resource
    private IEdosUtil edosUtil;

    // 计算光伏理论发电量
    public double calculateEnergy(List<PointData> lightData, double power) {
        double energy = 0.0;
        double theoreticalPower = 0.0;
        try {

            if (!lightData.isEmpty()) {
                List<PointData> filterls = new ArrayList<>();
                for (PointData po : lightData) {
                    if (po.getPointValueInDouble() > 10) {
                        filterls.add(po);
                    }
                }


                if (!filterls.isEmpty()) {
                    Date beginTime = new Date(filterls.get(0).getPointTime());
                    Date endTime = new Date(filterls.get(filterls.size() - 1).getPointTime());
                    double hours = DateUtils.hoursDiff(beginTime, endTime);

                    DoubleSummaryStatistics summaryStatistics = filterls.stream().mapToDouble(PointData::getPointValueInDouble).summaryStatistics();


                    double avg = StringUtils.round(summaryStatistics.getAverage(), 2);

                    double lightresult = new BigDecimal(avg * hours).divide(new BigDecimal(1000), 2, RoundingMode.HALF_EVEN).doubleValue();

                    theoreticalPower = lightresult * power;
                }


            }

        } catch (Exception e) {
            System.out.println("");
        }

        return theoreticalPower;
    }


    // 计算光伏理论发电量
    public PowerVo calculateEnergy(List<PointData> powerData, List<PointData> lightData, List<PointData> status, String pointid, double power) throws Exception {

        double lastState = -1;//上一分钟状态
        Date stateBegin;
        Date stateEnd;
        Map<Long, PointData> pmap = new HashMap<>();

        double llfdl = 0.0;
        double rfdl = 0.0;
        double rgzssdl = 0.0;
        double rcnslgzssdl = 0.0;
        double rjxssdl = 0.0;
        double rcnsljxssdl = 0.0;
        double rdjssdl = 0.0;
        double rqxjclssdl = 0.0;
        double rsdtjssdl = 0.0;
        double rxnssdl = 0.0;
        double rxdtjssdl = 0.0;
        double rxdjclssdl = 0.0;
        double rcwsldwssdl = 0.0;
        double rcwsltqssdl = 0.0;


        PowerVo vo = new PowerVo();
        vo.setLlfdl(llfdl);
        vo.setRfdl(rfdl);
        vo.setRgzssdl(rgzssdl);
        vo.setRcnslgzssdl(rcnslgzssdl);
        vo.setRjxssdl(rjxssdl);
        vo.setRcnsljxssdl(rcnsljxssdl);
        vo.setRdjssdl(rdjssdl);
        vo.setRqxjclssdl(rqxjclssdl);
        vo.setRsdtjssdl(rsdtjssdl);
        vo.setRxnssdl(rxnssdl);
        vo.setRxdtjssdl(rxdtjssdl);
        vo.setRxdjclssdl(rxdjclssdl);
        vo.setRcwsldwssdl(rcwsldwssdl);
        vo.setRcwsltqssdl(rcwsltqssdl);


        //        try {

        if (!status.isEmpty() && !powerData.isEmpty() && status.size() == powerData.size()) {
            llfdl = calculateEnergy(lightData, power);
            rfdl = powerData.get(powerData.size() - 1).getPointValueInDouble();
            stateBegin = new Date(status.get(0).getPointTime());
            stateEnd = new Date(status.get(status.size() - 1).getPointTime());
            for (PointData po : powerData) {
                pmap.put(po.getPointTime(), po);
            }
            for (PointData po : status) {

                Date temp = null;
                Calendar c = null;
                double lldl = 0.0;

                if (lastState != po.getPointValueInDouble()) {


                    switch ((int) po.getPointValueInDouble()) {
                        case 0:
                            //将当前状态保存到上一分钟状态
                            lastState = po.getPointValueInDouble();
                            stateEnd = new Date(po.getPointTime());

                            rdjssdl = getSsdl(pointid, stateBegin, stateEnd, pmap, rdjssdl);

                            //                            temp = new Date(po.getPointTime());
                            //                            c = Calendar.getInstance();
                            //                            c.setTime(temp);
                            //                            c.add(Calendar.MINUTE, 1);
                            //                            stateBegin = c.getTime();

                            stateBegin = new Date(po.getPointTime());
                            break;
                        case 1:
                            //将当前状态保存到上一分钟状态
                            lastState = po.getPointValueInDouble();
                            stateEnd = new Date(po.getPointTime());

                            rsdtjssdl = getSsdl(pointid, stateBegin, stateEnd, pmap, rsdtjssdl);

                            //                            temp = new Date(po.getPointTime());
                            //                            c = Calendar.getInstance();
                            //                            c.setTime(temp);
                            //                            c.add(Calendar.MINUTE, 1);
                            //                            stateBegin = c.getTime();

                            stateBegin = new Date(po.getPointTime());
                            break;
                        case 3:
                            lastState = po.getPointValueInDouble();
                            stateEnd = new Date(po.getPointTime());

                            rqxjclssdl = getSsdl(pointid, stateBegin, stateEnd, pmap, rqxjclssdl);

                            //                            temp = new Date(po.getPointTime());
                            //                            c = Calendar.getInstance();
                            //                            c.setTime(temp);
                            //                            c.add(Calendar.MINUTE, 1);
                            //                            stateBegin = c.getTime();

                            stateBegin = new Date(po.getPointTime());
                            break;
                        case 4:
                            //将当前状态保存到上一分钟状态
                            lastState = po.getPointValueInDouble();
                            stateEnd = new Date(po.getPointTime());

                            lldl = getLldl(pointid, stateBegin, stateEnd);
                            rgzssdl = rgzssdl + lldl;

                            //                            temp = new Date(po.getPointTime());
                            //                            c = Calendar.getInstance();
                            //                            c.setTime(temp);
                            //                            c.add(Calendar.MINUTE, 1);
                            //                            stateBegin = c.getTime();

                            stateBegin = new Date(po.getPointTime());
                            break;
                        case 5:
                            lastState = po.getPointValueInDouble();
                            stateEnd = new Date(po.getPointTime());

                            rcnslgzssdl = getSsdl(pointid, stateBegin, stateEnd, pmap, rcnslgzssdl);

                            //                            temp = new Date(po.getPointTime());
                            //                            c = Calendar.getInstance();
                            //                            c.setTime(temp);
                            //                            c.add(Calendar.MINUTE, 1);
                            //                            stateBegin = c.getTime();
                            stateBegin = new Date(po.getPointTime());
                            break;
                        case 6:
                            //将当前状态保存到上一分钟状态
                            lastState = po.getPointValueInDouble();
                            stateEnd = new Date(po.getPointTime());

                            lldl = getLldl(pointid, stateBegin, stateEnd);
                            rjxssdl = rjxssdl + lldl;

                            //                            temp = new Date(po.getPointTime());
                            //                            c = Calendar.getInstance();
                            //                            c.setTime(temp);
                            //                            c.add(Calendar.MINUTE, 1);
                            //                            stateBegin = c.getTime();
                            stateBegin = new Date(po.getPointTime());
                            break;
                        case 7:
                            lastState = po.getPointValueInDouble();
                            stateEnd = new Date(po.getPointTime());

                            rcnsljxssdl = getSsdl(pointid, stateBegin, stateEnd, pmap, rcnsljxssdl);

                            //                            temp = new Date(po.getPointTime());
                            //                            c = Calendar.getInstance();
                            //                            c.setTime(temp);
                            //                            c.add(Calendar.MINUTE, 1);
                            //                            stateBegin = c.getTime();
                            stateBegin = new Date(po.getPointTime());
                            break;
                        case 8:
                            lastState = po.getPointValueInDouble();
                            stateEnd = new Date(po.getPointTime());

                            rxdjclssdl = getSsdl(pointid, stateBegin, stateEnd, pmap, rxdjclssdl);

                            //                            temp = new Date(po.getPointTime());
                            //                            c = Calendar.getInstance();
                            //                            c.setTime(temp);
                            //                            c.add(Calendar.MINUTE, 1);
                            //                            stateBegin = c.getTime();
                            stateBegin = new Date(po.getPointTime());
                            break;
                        case 9:
                            //将当前状态保存到上一分钟状态
                            lastState = po.getPointValueInDouble();
                            stateEnd = new Date(po.getPointTime());

                            lldl = getLldl(pointid, stateBegin, stateEnd);
                            rxdtjssdl = rxdtjssdl + lldl;

                            //                            temp = new Date(po.getPointTime());
                            //                            c = Calendar.getInstance();
                            //                            c.setTime(temp);
                            //                            c.add(Calendar.MINUTE, 1);
                            //                            stateBegin = c.getTime();

                            stateBegin = new Date(po.getPointTime());
                            break;
                        case 10:
                            //将当前状态保存到上一分钟状态
                            lastState = po.getPointValueInDouble();
                            stateEnd = new Date(po.getPointTime());

                            lldl = getLldl(pointid, stateBegin, stateEnd);
                            rcwsldwssdl = rcwsldwssdl + lldl;

                            //                            temp = new Date(po.getPointTime());
                            //                            c = Calendar.getInstance();
                            //                            c.setTime(temp);
                            //                            c.add(Calendar.MINUTE, 1);
                            //                            stateBegin = c.getTime();
                            stateBegin = new Date(po.getPointTime());
                            break;
                        case 11:
                            //将当前状态保存到上一分钟状态
                            lastState = po.getPointValueInDouble();
                            stateEnd = new Date(po.getPointTime());

                            lldl = getLldl(pointid, stateBegin, stateEnd);
                            rcwsltqssdl = rcwsltqssdl + lldl;

                            //                            temp = new Date(po.getPointTime());
                            //                            c = Calendar.getInstance();
                            //                            c.setTime(temp);
                            //                            c.add(Calendar.MINUTE, 1);
                            //                            stateBegin = c.getTime();

                            stateBegin = new Date(po.getPointTime());
                            break;
                        case 12:
                            //将当前状态保存到上一分钟状态
                            lastState = po.getPointValueInDouble();


                            stateBegin = new Date(po.getPointTime());
                            break;
                        case 13:
                            //将当前状态保存到上一分钟状态
                            lastState = po.getPointValueInDouble();

                            stateBegin = new Date(po.getPointTime());
                            break;
                    }

                }

            }


        }

        vo.setLlfdl(llfdl);
        vo.setRfdl(rfdl);
        vo.setRgzssdl(rgzssdl);
        vo.setRcnslgzssdl(rcnslgzssdl);
        vo.setRjxssdl(rjxssdl);
        vo.setRcnsljxssdl(rcnsljxssdl);
        vo.setRdjssdl(rdjssdl);
        vo.setRqxjclssdl(rqxjclssdl);
        vo.setRsdtjssdl(rsdtjssdl);
        vo.setRxnssdl(rxnssdl);
        vo.setRxdtjssdl(rxdtjssdl);
        vo.setRxdjclssdl(rxdjclssdl);
        vo.setRcwsldwssdl(rcwsldwssdl);
        vo.setRcwsltqssdl(rcwsltqssdl);

        rxnssdl = llfdl - rfdl - rgzssdl - rcnslgzssdl - rjxssdl - rcnsljxssdl - rdjssdl - rqxjclssdl - rsdtjssdl - rxdtjssdl - rxdjclssdl - rcwsldwssdl - rcwsltqssdl;
        if (rxnssdl > 0) {

            vo.setRxnssdl(StringUtils.round(rxnssdl, 2));
        } else {
            vo.setRxnssdl(StringUtils.round(0, 2));
        }


        //        }catch (Exception e)
        //        {
        //            System.out.println("");
        //        }

        return vo;
    }

    private double getSsdl(String pointid, Date stateBegin, Date stateEnd, Map<Long, PointData> pmap, double ssdl) throws Exception {
        double begin = 0.0;
        double end = 0.0;
        if (pmap.containsKey(stateBegin.getTime())) {
            begin = pmap.get(stateBegin.getTime()).getPointValueInDouble();
        }
        if (pmap.containsKey(stateEnd.getTime())) {
            end = pmap.get(stateEnd.getTime()).getPointValueInDouble();
        }

        double lldl = getLldl(pointid, stateBegin, stateEnd);

        if (end > begin) {
            ssdl = ssdl + (lldl - (end - begin));
        }


        if (ssdl < 0) {
            ssdl = 0;
        }
        return ssdl;
    }

    private double getLldl(String pointid, Date stateBegin, Date stateEnd) throws Exception {

        double result = 0.0;
        if (stateBegin.getTime() < stateEnd.getTime() && DateUtils.secondsDiff(stateBegin, stateEnd) >= 60) {

            List<PointData> pointls = edosUtil.getHistoryDatasSnap(pointid, stateBegin.getTime() / 1000, stateEnd.getTime() / 1000);
            if (!pointls.isEmpty()) {
                List<PointData> filterls = new ArrayList<>();
                for (PointData p : pointls) {
                    if (p.getPointValueInDouble() > 10) {
                        filterls.add(p);
                    }
                }


                if (!filterls.isEmpty()) {
                    Date beginTime = new Date(filterls.get(0).getPointTime());
                    Date endTime = new Date(filterls.get(filterls.size() - 1).getPointTime());
                    double hours = DateUtils.hoursDiff(beginTime, endTime);

                    DoubleSummaryStatistics summaryStatistics = filterls.stream().mapToDouble(PointData::getPointValueInDouble).summaryStatistics();
                    double avg = StringUtils.round(summaryStatistics.getAverage(), 2);

                    result = new BigDecimal(avg * hours).divide(new BigDecimal(1000), 2, RoundingMode.HALF_EVEN).doubleValue();


                }


            }
        }

        return result;
    }
}
