package com.shining.cloud.serviceImpl.report;

import com.njcn.excelreport.GetOverlimitInfo;
import com.njcn.pojo.advanced.SagEvent;
import com.njcn.pojo.excelreport.*;
import com.njcn.pojo.excelreport.enumReport.EnumPassData;
import com.njcn.pojo.weeklyreport.AreaPointInfoData;
import com.njcn.pojo.weeklyreport.SagRateData;
import com.njcn.service.excelreport.*;
import com.njcn.service.weeklyreport.WeeklyReportDataService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.List;

@Component
public class ShiningReport {
    @Autowired
    private GetOverlimitInfo getOverlimitInfo;
    @Autowired
    private GetVirtualService getVirtualService;
    @Autowired
    private GetPowerService getPowerService;
    @Autowired
    private GetFlickerService getFlickerService;
    @Autowired
    private GetDistortionService getDistortionService;
    @Autowired
    private GetVdeviationService getVdeviationService;
    @Autowired
    private GetFrequencyService getFrequencyService;
    @Autowired
    private GetThreephaseService getThreephaseService;
    @Autowired
    private GetICurrentDataService getICurrentDataService;
    @Autowired
    private GetVoltageRateDataService getVoltageRateDataService;
    @Autowired
    private GetFpyDataService getFpyDataService;

    //非谐波数据
    private List<ReportTargetData> listVirtual;
    private List<ReportTargetData> listPower;
    private List<ReportTargetData> listFlicker;
    private List<ReportTargetData> listDistortion;
    private List<ReportTargetData> listVdeviation;
    private List<ReportTargetData> listFrequency;
    private List<ReportTargetData> listThreephase;
    //谐波电压数据
    private List<ReportTargetData> listVoltageRate;
    //谐波电流数据
    private List<ReportTargetData> listICurrent;
    //合格率数据
    private List<FpyByType> listFpy;
    private OverLimitInfoData overLimitInfoData;

    public OverLimitInfoData getOverLimitInfoData() {
        return overLimitInfoData;
    }

    //暂降月报
    @Autowired
    private WeeklyReportDataService weeklyReportDataService;
    private List<AreaPointInfoData> listPointInfo;
    private List<AreaPointInfoData> listVoltageInfo;
    private List<SagEvent> listSag;
    private List<SagRateData> listSagReason;
    private List<SagEvent> listSagEvents;

    public List<AreaPointInfoData> getListPointInfo() {
        return listPointInfo;
    }

    public List<AreaPointInfoData> getListVoltageInfo() {
        return listVoltageInfo;
    }

    public List<SagEvent> getListSag() {
        return listSag;
    }

    public List<SagRateData> getListSagReason() {
        return listSagReason;
    }

    public List<SagEvent> getListSagEvents() {
        return listSagEvents;
    }

    public List<ReportTargetData> getListVirtual() {
        return listVirtual;
    }

    public List<ReportTargetData> getListPower() {
        return listPower;
    }

    public List<ReportTargetData> getListFlicker() {
        return listFlicker;
    }

    public List<ReportTargetData> getListDistortion() {
        return listDistortion;
    }

    public List<ReportTargetData> getListVdeviation() {
        return listVdeviation;
    }

    public List<ReportTargetData> getListFrequency() {
        return listFrequency;
    }

    public List<ReportTargetData> getListThreephase() {
        return listThreephase;
    }

    public List<ReportTargetData> getListVoltageRate() {
        return listVoltageRate;
    }

    public List<ReportTargetData> getListICurrent() {
        return listICurrent;
    }

    public List<FpyByType> getListFpy() {
        return listFpy;
    }

    public enum REPORTRETURN {
        RESULT_SUCCESS(0, "成功"),
        RESULT_FAIL(1, "失败"),
        RESULT_ERROR(2, "监测点无限值"),
        RESULT_NULL(3, "指标获取失败");

        private int code;
        private String msg;

        REPORTRETURN(int code, String msg) {
            this.code = code;
            this.msg = msg;
        }

        public int getCode() {
            return code;
        }

        public void setCode(int code) {
            this.code = code;
        }

        public String getMsg() {
            return msg;
        }

        public void setMsg(String msg) {
            this.msg = msg;
        }
    }

    public REPORTRETURN createTransientReport(String userIndex, Date startTime, Date endTime) {
        try {
            getPointData(userIndex, startTime, endTime);
            getVoltageData(userIndex, startTime, endTime);
            getSagData(userIndex, startTime, endTime);
            getSagEvents(userIndex, startTime, endTime);
            getSagReasonData(userIndex, startTime, endTime);
        } catch (Exception e) {
            return REPORTRETURN.RESULT_NULL;
        }

        return REPORTRETURN.RESULT_SUCCESS;
    }

    private void getPointData(String userIndex, Date start, Date end) {
        this.listPointInfo = weeklyReportDataService.getPointData(userIndex, start, end);
        Collections.sort(this.listPointInfo);
    }

    private void getVoltageData(String userIndex, Date start, Date end) {
        this.listVoltageInfo = weeklyReportDataService.getVoltageData(userIndex, start, end);
        Collections.sort(this.listVoltageInfo);
    }

    private void getSagData(String userIndex, Date start, Date end) {
        this.listSag = weeklyReportDataService.getSagData(userIndex, start, end);
    }

    private void getSagReasonData(String userIndex, Date start, Date end) {
        this.listSagReason = weeklyReportDataService.getSagReasonData(userIndex, start, end);
    }

    private void getSagEvents(String userIndex, Date start, Date end) {
        this.listSagEvents = weeklyReportDataService.getSagEvents(userIndex, start, end);
    }

    public REPORTRETURN createReport(Integer lineId, Date startTime, Date endTime) {
        ConditionData conditionData = getOverlimitInfo.getConditionData();
        conditionData.setStart(startTime);
        conditionData.setEnd(endTime);
        conditionData.setPointIndex(lineId);

        OverLimitInfoData overLimitInfoData;

        try {
            overLimitInfoData = getOverLimitInfo(lineId);
        } catch (Exception e) {
            return REPORTRETURN.RESULT_FAIL;
        }

        if (0 == overLimitInfoData.getOverLimitRate().size()) {
            return REPORTRETURN.RESULT_ERROR;
        }

        try {
            this.overLimitInfoData = overLimitInfoData;
            getVirtualData(conditionData);
            getPowerData(conditionData);
            getFlickerData(conditionData, overLimitInfoData);
            getDistortionData(conditionData, overLimitInfoData);
            getVdeviationData(conditionData, overLimitInfoData);
            getFrequencyData(conditionData, overLimitInfoData);
            getThreephaseData(conditionData, overLimitInfoData);
            getICurrent(conditionData, overLimitInfoData);
            getVoltageRate(conditionData, overLimitInfoData);
            getFpy(conditionData);

        } catch (Exception e) {
            return REPORTRETURN.RESULT_NULL;
        }

        return REPORTRETURN.RESULT_SUCCESS;
    }

    private OverLimitInfoData getOverLimitInfo(Integer lineId) {
        return getOverlimitInfo.getOverLimit(lineId);
    }

    private void getFpy(ConditionData conditionData) {
        this.listFpy = getFpyDataService.getFpy(conditionData);
    }

    private void getVoltageRate(ConditionData conditionData, OverLimitInfoData overLimitInfoData) {
        List<ReportValueData> listVoltageRate = getVoltageRateDataService.getVoltageRate(conditionData);
        List<PassData> list = new ArrayList<>();

        for (int i = 0; i < 51; i++) {
            PassData passData;

            if (i == 0) {
                passData = new PassData(null);
            } else if (i == 50) {
                passData = new PassData(overLimitInfoData.getOverLimitRate().get(0).getUaberrance(), EnumPassData.MAX.getCode());
            } else if (i < overLimitInfoData.getOverLimitRate().get(0).getVHarmList().size() + 1) {
                passData = new PassData(overLimitInfoData.getOverLimitRate().get(0).getVHarmList().get(i - 1), EnumPassData.CP95.getCode());
            } else {
                passData = new PassData(null);
            }

            list.add(passData);
        }

        this.listVoltageRate = new ArrayList<>();
        transformData(this.listVoltageRate, listVoltageRate, list, true);
    }

    private void getICurrent(ConditionData conditionData, OverLimitInfoData overLimitInfoData) {
        List<ReportValueData> listICurrent = getICurrentDataService.getICurrent(conditionData);
        List<PassData> list = new ArrayList<>();

        for (int i = 0; i < 50; i++) {
            PassData passData;

            if (i < overLimitInfoData.getOverLimitRate().get(0).getIHarmList().size() + 1 && i > 0) {
                passData = new PassData(overLimitInfoData.getOverLimitRate().get(0).getIHarmList().get(i - 1), EnumPassData.CP95.getCode());
            } else {
                passData = new PassData(null);
            }

            list.add(passData);
        }

        this.listICurrent = new ArrayList<>();
        transformData(this.listICurrent, listICurrent, list, true);
    }

    private void getThreephaseData(ConditionData conditionData, OverLimitInfoData overLimitInfoData) {
        List<ReportValueData> listThreephase = getThreephaseService.getThreephase(conditionData);
        List<PassData> list = new ArrayList<>();

        for (int i = 0; i < 8; i++) {
            PassData passData;

            if (i == 0) {
                passData = new PassData(overLimitInfoData.getOverLimitRate().get(0).getUbalance(), EnumPassData.CP95.getCode());
            } else {
                passData = new PassData(null);
            }

            list.add(passData);
        }

        this.listThreephase = new ArrayList<>();
        transformData(this.listThreephase, listThreephase, list, false);
    }

    private void getFrequencyData(ConditionData conditionData, OverLimitInfoData overLimitInfoData) {
        List<ReportValueData> listFrequency = getFrequencyService.getFrequencyData(conditionData);

        List<PassData> list = new ArrayList<>();

        for (int i = 0; i < 2; i++) {
            PassData passData;

            if (i == 1) {
                passData = new PassData(overLimitInfoData.getOverLimitRate().get(0).getFreqDev(), EnumPassData.MAX.getCode());
            } else {
                passData = new PassData(null);
            }

            list.add(passData);
        }

        this.listFrequency = new ArrayList<>();
        transformData(this.listFrequency, listFrequency, list, false);
    }

    private void getVdeviationData(ConditionData conditionData, OverLimitInfoData overLimitInfoData) {
        List<ReportValueData> listVdeviation = getVdeviationService.getVdeviation(conditionData);
        List<PassData> list = new ArrayList<>();

        for (int i = 0; i < 2; i++) {
            PassData passData;
            passData = new PassData(overLimitInfoData.getOverLimitRate().get(0).getVoltageDev(), EnumPassData.MAX.getCode());
            list.add(passData);
        }

        this.listVdeviation = new ArrayList<>();
        transformData(this.listVdeviation, listVdeviation, list, true);
    }

    private void getDistortionData(ConditionData conditionData, OverLimitInfoData overLimitInfoData) {
        List<ReportValueData> listDistortion = getDistortionService.getDistortionData(conditionData);
        List<PassData> list = new ArrayList<>();

        for (int i = 0; i < 2; i++) {
            PassData passData;

            if (i == 0) {
                passData = new PassData(overLimitInfoData.getOverLimitRate().get(0).getUaberrance(), EnumPassData.CP95.getCode());
            } else {
                passData = new PassData(null);
            }

            list.add(passData);
        }

        this.listDistortion = new ArrayList<>();
        transformData(this.listDistortion, listDistortion, list, true);
    }

    private void getFlickerData(ConditionData conditionData, OverLimitInfoData overLimitInfoData) {
        List<ReportValueData> listFlicker = getFlickerService.getFlickerData(conditionData);
        List<PassData> list = new ArrayList<>();

        for (int i = 0; i < 2; i++) {
            PassData passData;

            if (i == 1) {
                passData = new PassData(overLimitInfoData.getOverLimitRate().get(0).getFlicker(), EnumPassData.MAX.getCode());
            } else {
                passData = new PassData(null);
            }

            list.add(passData);
        }

        this.listFlicker = new ArrayList<>();
        transformData(this.listFlicker, listFlicker, list, true);
    }

    private void getPowerData(ConditionData conditionData) {
        List<ReportValueData> listPower = getPowerService.getPowerData(conditionData);
        List<PassData> list = new ArrayList<>();

        for (int i = 0; i < 4; i++) {
            PassData passData = new PassData(null);
            list.add(passData);
        }

        this.listPower = new ArrayList<>();
        transformData(this.listPower, listPower, list, true, false);
    }

    private void getVirtualData(ConditionData conditionData) {
        List<ReportValueData> listVirtual = getVirtualService.getVirtualData(conditionData);
        List<PassData> list = new ArrayList<>();

        for (int i = 0; i < 3; i++) {
            PassData passData = new PassData(null);
            list.add(passData);
        }

        this.listVirtual = new ArrayList<>();
        transformData(this.listVirtual, listVirtual, list, true);
    }

    private void transformData(List<ReportTargetData> list, List<ReportValueData> listValue, List<PassData> listOverlimit, boolean... b) {
        int offset = b[0] ? 3 : 1;
        offset = (b.length == 2 && !b[1]) ? 4 : offset;
        int i = 0;

        for (int index = 0; index < listValue.size(); index += offset) {
            ReportTargetData reportTargetData = new ReportTargetData();
            reportTargetData.setList(listValue.subList(index, index + offset));
            Float overLimit = listOverlimit.get(i).getOverLimit();
            reportTargetData.setOverLimit(overLimit);

            switch (listOverlimit.get(i).getCode()) {
                case 1:
                    for (int k = 0; k < reportTargetData.getList().size(); k++) {
                        if (null == reportTargetData.getList().get(k).getFmaxValue()) {
                            break;
                        } else if (reportTargetData.getList().get(k).getFmaxValue().floatValue() > overLimit.floatValue()) {
                            reportTargetData.setPass(EnumPassData.NOPASS.getCode());
                            break;
                        } else {
                            reportTargetData.setPass(EnumPassData.PASS.getCode());
                        }
                    }
                    break;
                case 2:
                    for (int k = 0; k < reportTargetData.getList().size(); k++) {
                        if (null == reportTargetData.getList().get(k).getMinValue()) {
                            break;
                        } else if (reportTargetData.getList().get(k).getMinValue().floatValue() > overLimit.floatValue()) {
                            reportTargetData.setPass(EnumPassData.NOPASS.getCode());
                            break;
                        } else {
                            reportTargetData.setPass(EnumPassData.PASS.getCode());
                        }
                    }
                    break;
                case 3:
                    for (int k = 0; k < reportTargetData.getList().size(); k++) {
                        if (null == reportTargetData.getList().get(k).getMeanValue()) {
                            break;
                        } else if (reportTargetData.getList().get(k).getMeanValue().floatValue() > overLimit.floatValue()) {
                            reportTargetData.setPass(EnumPassData.NOPASS.getCode());
                            break;
                        } else {
                            reportTargetData.setPass(EnumPassData.PASS.getCode());
                        }
                    }
                    break;
                case 4:
                    for (int k = 0; k < reportTargetData.getList().size(); k++) {
                        if (null == reportTargetData.getList().get(k).getCp95Value()) {
                            break;
                        } else if (reportTargetData.getList().get(k).getCp95Value().floatValue() > overLimit.floatValue()) {
                            reportTargetData.setPass(EnumPassData.NOPASS.getCode());
                            break;
                        } else {
                            reportTargetData.setPass(EnumPassData.PASS.getCode());
                        }
                    }
                    break;
                default:
                    break;
            }

            i++;
            list.add(reportTargetData);
        }
    }
}
