package com.pqs9000.serviceimpl.report;

import com.njcn.mapper.excelreport.PercentMapper;
import com.njcn.pojo.data.LimitRate;
import com.pqs9000.service.report.PercentService;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

@Service
public class PercentServiceImpl implements PercentService {
    @Autowired
    private PercentMapper percentMapper;

    @Override
    public XWPFDocument createTable(Date start, Date end, List<Integer> pointList, int timeType, String factory, String listPointName, String lineName) {
        String tableName = setTableTitle(start, end, timeType, pointList) + factory;

        if (tableName.equals("nodata")) {
            return null;
        }

        XWPFDocument document = new XWPFDocument();
        XWPFParagraph titleParagraph = getCenterParagraph(document);
        XWPFRun titleParagraphDateRun = titleParagraph.createRun();
        addLine(titleParagraph, 1);
        addParagraph(titleParagraphDateRun, "宋体", 14, "000000", tableName, false);
        titleParagraphDateRun = titleParagraph.createRun();
        addParagraph(titleParagraphDateRun, "宋体", 14, "000000", "电能质量稳态指标合格率统计表", false);

        try {
            XWPFTable table = document.createTable();

            CTTblPr tblPr = table.getCTTbl().getTblPr();
            tblPr.getTblW().setType(STTblWidth.DXA);
            tblPr.getTblW().setW(new BigInteger("8300"));

            setTableTitle(table, listPointName, lineName);
            List<List<Object>> lists = new ArrayList<>();
            List<Object> list = new ArrayList<>();

            List<LimitRate> limitRateList = getData(pointList, start, end);

            setTableData(lists, "系统频率", 99.5f, setData(limitRateList, 1, 0));
            setTableData(lists, "电压偏差", 98f, setData(limitRateList, 2, 0));
            setTableData(lists, "电压总谐波畸变率", 98f, setData(limitRateList, 3, 0));

            for (int i = 2; i < 26; i++) {
                setTableData(lists, i + "次谐波电压含有率", 98f, setData(limitRateList, 4, i));
            }

            for (int i = 0; i < 10; i++) {
                if (i < pointList.size()) {
                    list.add("/");
                } else {
                    list.add("");
                }
            }

            for (int i = 26; i < 51; i++) {
                setTableData(lists, i + "次谐波电压含有率", 98f, list);
            }

            for (int i = 2; i < 26; i++) {
                setTableData(lists, i + "次谐波电流含有率", 98f, setData(limitRateList, 5, i));
            }

            for (int i = 26; i < 51; i++) {
                setTableData(lists, i + "次谐波电流含有率", 98f, list);
            }

            setTableData(lists, "三相电压不平衡度", 98f, setData(limitRateList, 6, 0));
            setTableData(lists, "长时电压闪变值", 99f, setData(limitRateList, 7, 0));

            setValue(lists, table);

            setWidth(table.getRow(table.getRows().size() - 1).getCell(0), "1200");
            setWidth(table.getRow(table.getRows().size() - 1).getCell(1), "600");

            for (int i = 2; i < 12; i++) {
                setWidth(table.getRow(table.getRows().size() - 1).getCell(i), "650");
            }

            setHeight(table);

            return document;
        } catch (Exception e) {
            return null;
        }
    }

    public void setHeight(XWPFTable table) {
        List<XWPFTableRow> rows = table.getRows();
        for (XWPFTableRow row : rows) {
            CTTrPr trPr = row.getCtRow().addNewTrPr();
            CTHeight ht = trPr.addNewTrHeight();
            ht.setVal(new BigInteger("460"));
        }
    }

    public List<Object> setData(List<LimitRate> limitRateList, int type, int index) {
        List<Object> list = new ArrayList<>();

        for (int i = 0; i < 10; i++) {
            if (i < limitRateList.size()) {
                Object object = null;

                if (limitRateList.get(i) == null || limitRateList.get(i).getAllTime() == null || limitRateList.get(i).getFlicketAllTime() == null) {
                    list.add(object == null ? "/" : object);
                    continue;
                }

                if (type == 1) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getFreqDevOverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 2) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getVoltageDevOvertime(), limitRateList.get(i).getAllTime());
                } else if (type == 3) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUAberranceOverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 6) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUBalanceOverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 7) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getFlickerOverTime(), limitRateList.get(i).getFlicketAllTime());
                } else if (type == 4 && index == 2) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm2OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 3) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm3OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 4) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm4OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 5) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm5OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 6) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm6OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 7) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm7OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 8) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm8OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 9) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm9OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 10) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm10OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 11) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm11OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 12) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm12OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 13) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm13OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 14) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm14OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 15) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm15OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 16) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm16OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 17) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm17OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 18) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm18OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 19) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm19OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 20) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm20OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 21) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm21OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 22) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm22OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 23) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm23OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 24) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm24OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 4 && index == 25) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getUHarm25OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 2) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm2OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 3) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm3OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 4) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm4OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 5) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm5OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 6) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm6OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 7) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm7OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 8) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm8OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 9) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm9OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 10) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm10OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 11) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm11OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 12) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm12OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 13) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm13OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 14) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm14OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 15) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm15OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 16) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm16OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 17) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm17OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 18) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm18OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 19) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm19OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 20) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm20OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 21) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm21OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 22) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm22OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 23) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm23OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 24) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm24OverTime(), limitRateList.get(i).getAllTime());
                } else if (type == 5 && index == 25) {
                    object = limitRateList.get(i) == null ? "/" : judgeRate(limitRateList.get(i).getIHarm25OverTime(), limitRateList.get(i).getAllTime());
                }

                list.add(object);
            } else {
                list.add("");
            }
        }

        return list;
    }

    public Float judgeRate(Integer l, Integer l1) {
        float d = 100.0f - (l * 1.0f / (l1 == 0 ? 1 : l1)) * 100.0f;
        d = (float) (Math.round(d * 100)) / 100;
        return new Float(d < 0.0f ? 0.0f : d);
    }

    public List<LimitRate> getData(List<Integer> list, Date start, Date end) {
        List<LimitRate> lists = new ArrayList<>();
        List<Integer> list1 = new ArrayList<>();

        for (int i = 2; i < 26; i++) {
            list1.add(i);
        }

        for (int i = 0; i < list.size(); i++) {
            lists.add(percentMapper.getFpy(list1, list.get(i), start, end));
        }

        return lists;
    }

    public void setTableData(List<List<Object>> lists, String target, Float overlimit, List<Object> l) {
        List<Object> list = new ArrayList<>();
        list.add(target);
        list.add(overlimit + "%");

        for (int i = 0; i < l.size(); i++)
            list.add(l.get(i));

        list.add(overlimit);

        lists.add(list);
    }

    public void setTableTitle(XWPFTable table, String listPointName, String lineName) {
        XWPFTableRow rowsContent = table.getRow(0);
        setStyle(0, "统计指标", rowsContent, false);
        rowsContent.addNewTableCell();
        setStyle(1, "合格率限值", rowsContent, false);
        rowsContent.addNewTableCell();
        setStyle(2, "电能质量稳态指标合格率统计表", rowsContent, false);

        for (int i = 3; i < 12; i++) {
            rowsContent.addNewTableCell();
            setStyle(i, "", rowsContent, false);
        }

        mergeCellsHorizontal(table, 0, 2, 11);

        XWPFTableRow tableRowTwo = table.createRow();
        setStyle(0, "", tableRowTwo, false);
        setStyle(1, "", tableRowTwo, false);

        String[] pointName = listPointName.split(",");
        String[] lineNames = lineName.split(",");

        for (int i = 2; i < 12; i++) {
            if (i < pointName.length + 2) {
                setStyle(i, pointName[i - 2] + "（" + lineNames[i - 2] + "）", tableRowTwo, false);
            } else {
                setStyle(i, "", tableRowTwo, false);
            }
        }

        mergeCellsVertically(table, 0, 0, 1);
        mergeCellsVertically(table, 1, 0, 1);
    }

    public void setWidth(XWPFTableCell cell, String width) {
        CTTcPr tcpr = cell.getCTTc().addNewTcPr();
        CTTblWidth cellw = tcpr.addNewTcW();
        cellw.setW(new BigInteger(width));
        cellw.setType(STTblWidth.DXA);
    }

    public static void setStyle(int pos, String value, XWPFTableRow rowsContent, Boolean b) {
        XWPFParagraph cellParagraphC = rowsContent.getCell(pos).getParagraphs().get(0);
        cellParagraphC.setAlignment(ParagraphAlignment.CENTER); //设置表格内容居中
        rowsContent.getCell(pos).setVerticalAlignment(XWPFTableCell.XWPFVertAlign.CENTER);
        XWPFRun cellParagraphRunC = cellParagraphC.createRun();
        cellParagraphRunC.setFontSize(9); //设置表格内容字号

        if (b)
            cellParagraphRunC.setColor("ff0000");

        cellParagraphRunC.setText(value); //单元格段落加载内容
    }

    //添加内容并设置水平居中
    public void setValue(List<List<Object>> list, XWPFTable table) {
        for (int j = 0; j < list.size(); j++) {
            XWPFTableRow rowsContent = table.createRow();

            for (int i = 0; i < list.get(j).size() - 1; i++) {
                if (list.get(j).get(i).toString().equals("") || list.get(j).get(i).toString().equals("/") || i < 2)
                    setStyle(i, list.get(j).get(i).toString(), rowsContent, false);
                else {
                    Boolean b = ((Float) list.get(j).get(i)).floatValue() < ((Float) list.get(j).get(list.get(j).size() - 1)).floatValue();
                    setStyle(i, list.get(j).get(i).toString() + "%", rowsContent, b);
                }
            }
        }
    }

    //跨行合并单元格
    public void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) {
        for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
            XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
            if (rowIndex == fromRow) {
                cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
            } else {
                cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
            }
        }
    }

    //跨列合并单元格
    public void mergeCellsHorizontal(XWPFTable table, int row, int fromCell, int toCell) {
        for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) {
            XWPFTableCell cell = table.getRow(row).getCell(cellIndex);
            if (cellIndex == fromCell) {
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
            } else {
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
            }
        }
    }

    public void addParagraph(XWPFRun run, String fontFamily, Integer fontSize, String backgroundColor, String
            message, boolean bold) {
        run.setText(message);
        run.setColor(backgroundColor);
        run.setFontSize(fontSize);
        run.setFontFamily(fontFamily);
        run.setBold(bold);
    }

    public void addLine(XWPFParagraph paragraph, Integer amount) {
        XWPFRun run = paragraph.createRun();
        run.setFontSize(11);
        for (int i = 0; i < amount; i++) {
            run.addCarriageReturn();
        }
    }

    public XWPFParagraph getCenterParagraph(XWPFDocument document) {
        XWPFParagraph paragraph = document.createParagraph();
        setParagraphStyle(paragraph);
        paragraph.setAlignment(ParagraphAlignment.CENTER);
        paragraph.setVerticalAlignment(TextAlignment.CENTER);
        return paragraph;
    }

    public void setParagraphStyle(XWPFParagraph paragraph) {
        paragraph.setSpacingBefore(100);
        paragraph.setSpacingAfter(100);
    }

    public String setTableTitle(Date start, Date end, Integer timeType, List<Integer> list) {
        String time = getTime(start, end, timeType);

        if (list.size() == 0) {
            return "nodata";
        }

        return time;
    }

    public String getTime(Date start, Date end, Integer timeType) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(start);
        String year1 = calendar.get(Calendar.YEAR) + "年";
        int month1 = calendar.get(Calendar.MONTH) + 1;

        switch (timeType) {
            case 1:
                return year1;
            case 2: {
                switch (month1) {
                    case 1:
                        return year1 + "第1季度";
                    case 4:
                        return year1 + "第2季度";
                    case 7:
                        return year1 + "第3季度";
                    case 10:
                        return year1 + "第4季度";
                }
            }
            case 3:
                return year1 + month1 + "月";
            case 4: {
                int day1 = calendar.get(Calendar.DATE);
                String dayStr1 = (day1 < 10 ? "0" + day1 : day1) + "日";
                Calendar calendar1 = Calendar.getInstance();
                calendar1.setTime(end);
                String year2 = calendar1.get(Calendar.YEAR) + "年";
                int month2 = calendar1.get(Calendar.MONTH) + 1;
                int day2 = calendar1.get(Calendar.DATE);
                String dayStr2 = (day2 < 10 ? "0" + day2 : day2) + "日";
                return year1 + month1 + "月" + dayStr1 + " 至 " + year2 + month2 + "月" + dayStr2;
            }
            default:
                return "";
        }
    }
}