package com.njcn.cloud.utils;

import cn.hutool.core.date.LocalDateTimeUtil;
import com.njcn.cloud.pojo.vo.EventEigDetailVO;
import com.njcn.cloud.pojo.vo.EventInfoDetailVO;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import sun.misc.BASE64Decoder;

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;

public class WordUtil {
    private List<byte[]> listPic;
    private XWPFDocument document;
    private List<EventEigDetailVO> eventDetailEigenvalue;
    private EventInfoDetailVO eventInfoList;

    public void setEventInfoList(EventInfoDetailVO eventInfoList) {
        this.eventInfoList = eventInfoList == null ? new EventInfoDetailVO() : eventInfoList;
    }

    public void setEventDetailEigenvalue(List<EventEigDetailVO> eventDetailEigenvalue) {
        this.eventDetailEigenvalue = eventDetailEigenvalue == null ? new ArrayList<>() : eventDetailEigenvalue;
    }

    public XWPFDocument getDocument() {
        return document;
    }

    public WordUtil() {
        this.document = new XWPFDocument();
        listPic = new ArrayList<>();
    }

    public void translate(String... strPic) {
        BASE64Decoder decoder = new BASE64Decoder();

        for (int i = 0; i < strPic.length; i++) {
            try {
                byte[] buffer = decoder.decodeBuffer(strPic[i]);
                listPic.add(buffer);
            } catch (Exception e) {
            }
        }
    }

    public void createReport() throws IOException, InvalidFormatException {
        setHeadingStyle(this.document);

        // 添加标题
        XWPFParagraph titleParagraph = getCenterParagraph(this.document);
        addLine(titleParagraph, 11);
        // 设置段落居中
        XWPFRun titleParagraphBigRun = titleParagraph.createRun();
        addParagraph(titleParagraphBigRun, "宋体", 28, "000000", "暂降事件报告", true);
        addLine(titleParagraph, 17);
        XWPFRun titleParagraphDateRun = titleParagraph.createRun();
        addParagraph(titleParagraphDateRun, "宋体", 16, "000000", "南京灿能电力自动化股份有限公司", false);
        addLine(titleParagraph, 1);
        titleParagraphDateRun = titleParagraph.createRun();
        addParagraph(titleParagraphDateRun, "宋体", 14, "000000", "生成时间：" + getRightNow(), false);
        addLine(titleParagraph, 8);
        titleParagraph = getLeftParagraph(this.document);
        titleParagraphDateRun = titleParagraph.createRun();
        addParagraph(titleParagraphDateRun, "宋体", 10, "000000", "【申明】本公司保留对报告的修改权，恕不另行通知，敬请关注最新版本。", false);
        createTitle(document, "1. 基本信息", "标题 1", 0, 15);
        XWPFParagraph introductionContentParagraph = getLeftParagraph(document);
        introductionContentParagraph.setIndentationFirstLine(200);
        XWPFRun introductionContentRun = introductionContentParagraph.createRun();
        String time = LocalDateTimeUtil.format(eventInfoList.getTimeID(), DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS"));
        addParagraph(introductionContentRun, "宋体", 11, "000000",
                eventInfoList.getGdName() + "，" + eventInfoList.getBdzName() + "，网络参数：" +
                        eventInfoList.getIp() + "，" + eventInfoList.getLineName() + "于" + time + "发生暂降事件，特征幅值："
                        + String.valueOf(eventInfoList.getEventValue()) + "%，持续时间：" + eventInfoList.getPersistTime() + "s。",
                false);
        createTitle(document, "2. 波形图", "标题 1", 0, 15);
        if(listPic.size() == 2){
            createTitle(document, "2.1 瞬时波形图", "标题 2", 200, 11);
            createPic(document, "瞬时波形", listPic.get(0));
            createTitle(document, "2.2 RMS波形图", "标题 2", 200, 11);
            createPic(document, "RMS波形", listPic.get(1));
        }else{
            createTitle(document, "2.1 瞬时波形图", "标题 2", 200, 11);
            createPic(document, "瞬时波形1", listPic.get(0));
            createPic(document, "瞬时波形2", listPic.get(1));
            createTitle(document, "2.2 RMS波形图", "标题 2", 200, 11);
            createPic(document, "RMS波形3", listPic.get(2));
            createPic(document, "RMS波形4", listPic.get(3));
        }
        createTitle(document, "3. 多特征值", "标题 1", 0, 15);

        XWPFParagraph value = getLeftParagraph(document);
        XWPFRun valuex = value.createRun();
        addParagraph(valuex, "宋体", 11, "000000", "事件总分段数：" + this.eventDetailEigenvalue.size(),
                false);
        addLine(value, 1);

        if (this.eventDetailEigenvalue.size() == 0) {
            return;
        }
        valuex = value.createRun();
        addParagraph(valuex, "宋体", 11, "000000", "暂降原因：" + this.eventDetailEigenvalue.get(0).getSagReason(),
                false);
        addLine(value, 1);

        for (int i = 0; i < this.eventDetailEigenvalue.size(); i++) {
            valuex = value.createRun();
            addParagraph(valuex, "宋体", 11, "000000", "分段" + (i + 1) + "多特征值",
                    true);
            addLine(value, 1);
            valuex = value.createRun();
            addParagraph(valuex, "宋体", 11, "000000", "波形起始点相位(°)：" + (this.eventDetailEigenvalue.get(0).getPttype() == 0 ? "A" : "AB") + "相" + this.eventDetailEigenvalue.get(i).getPow_a()
                            + "   " + (this.eventDetailEigenvalue.get(0).getPttype() == 0 ? "B" : "BC") + "相" + this.eventDetailEigenvalue.get(i).getPow_b() + "   " + ((this.eventDetailEigenvalue.get(0).getPttype() == 2) ? "" : ((this.eventDetailEigenvalue.get(0).getPttype() == 0 ? "C" : "CA") + "相" + this.eventDetailEigenvalue.get(i).getPow_c())),
                    false);
            addLine(value, 1);
            valuex = value.createRun();
            addParagraph(valuex, "宋体", 11, "000000", "跳变段电压变化率(V/ms)：" + (this.eventDetailEigenvalue.get(0).getPttype() == 0 ? "A" : "AB") + "相" + this.eventDetailEigenvalue.get(i).getVoltagechange_Va()
                            + "   " + (this.eventDetailEigenvalue.get(0).getPttype() == 0 ? "B" : "BC") + "相" + this.eventDetailEigenvalue.get(i).getVoltagechange_Vb() + "   " + ((this.eventDetailEigenvalue.get(0).getPttype() == 2) ? "" : ((this.eventDetailEigenvalue.get(0).getPttype() == 0 ? "C" : "CA") + "相" + this.eventDetailEigenvalue.get(i).getVoltagechange_Vc())),
                    false);
            addLine(value, 1);
            valuex = value.createRun();
            addParagraph(valuex, "宋体", 11, "000000", "相位跳变(°)：" + (this.eventDetailEigenvalue.get(0).getPttype() == 0 ? "A" : "AB") + "相" + this.eventDetailEigenvalue.get(i).getAngle_diff_ap()
                            + "   " + (this.eventDetailEigenvalue.get(0).getPttype() == 0 ? "B" : "BC") + "相" + this.eventDetailEigenvalue.get(i).getAngle_diff_bp() + "   " + ((this.eventDetailEigenvalue.get(0).getPttype() == 2) ? "" : ((this.eventDetailEigenvalue.get(0).getPttype() == 0 ? "C" : "CA") + "相" + this.eventDetailEigenvalue.get(i).getAngle_diff_cp())),
                    false);
            /*addLine(value, 1);
            valuex = value.createRun();
            addParagraph(valuex, "宋体", 11, "000000", "特征幅值(V)：A相" + this.eventDetailEigenvalue.get(i).getUa_min()
                            + "   B相" + this.eventDetailEigenvalue.get(i).getUb_min() + "   C相" + this.eventDetailEigenvalue.get(i).getUc_min(),
                    false);*/
            /*addLine(value, 1);
            valuex = value.createRun();
            addParagraph(valuex, "宋体", 11, "000000", "持续时间(ms)：" + this.eventDetailEigenvalue.get(i).getHold_time_dq(),
                    false);*/
            addLine(value, 1);
            valuex = value.createRun();
            addParagraph(valuex, "宋体", 11, "000000", "三相电压不平衡度(%)：" + this.eventDetailEigenvalue.get(i).getBph_max_value(),
                    false);
            addLine(value, 1);
            valuex = value.createRun();
            addParagraph(valuex, "宋体", 11, "000000", "暂降类型：" + this.eventDetailEigenvalue.get(i).getSagType(),
                    false);
            addLine(value, 1);
        }
    }

    public void createPic(XWPFDocument document, String name, byte[] base64Info) throws IOException, InvalidFormatException {
        XWPFParagraph picParagraph = getCenterParagraph(document);
        XWPFRun createRun = picParagraph.createRun();
        InputStream in = new ByteArrayInputStream(base64Info);
        createRun.addPicture(in, 5, name, Units.toEMU(410), Units.toEMU(400));
    }

    public void createTitle(XWPFDocument document, String message, String style, int line, int fontSize) {
        XWPFParagraph summaeTableParagraph = getLeftParagraph(document);
        summaeTableParagraph.setStyle(style);
        summaeTableParagraph.setIndentationFirstLine(line);
        XWPFRun summaeTableRun = summaeTableParagraph.createRun();
        addParagraph(summaeTableRun, "宋体", fontSize, "000000", message, false);
    }

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

    /**
     * 返回指定格式的段落 居中型
     *
     * @param document 文档对象
     */
    public XWPFParagraph getCenterParagraph(XWPFDocument document) {
        XWPFParagraph paragraph = document.createParagraph();
        setParagraphStyle(paragraph);
        paragraph.setAlignment(ParagraphAlignment.CENTER);
        paragraph.setVerticalAlignment(TextAlignment.CENTER);
        return paragraph;
    }

    /**
     * 返回指定格式的段落 居左型
     *
     * @param document 文档对象
     */
    public XWPFParagraph getLeftParagraph(XWPFDocument document) {
        XWPFParagraph paragraph = document.createParagraph();
        setParagraphStyle(paragraph);
        paragraph.setAlignment(ParagraphAlignment.LEFT);
        return paragraph;
    }


    /**
     * 添加换行符
     *
     * @param paragraph 指定段落
     * @param amount    行数
     */
    public void addLine(XWPFParagraph paragraph, Integer amount) {
        XWPFRun run = paragraph.createRun();
        run.setFontSize(11);
        for (int i = 0; i < amount; i++) {
            run.addCarriageReturn();
        }
    }


    /**
     * 添加段落文本
     *
     * @param run             文本执行对象
     * @param fontFamily      字体类型
     * @param fontSize        字体大小
     * @param backgroundColor 字体颜色
     * @param bold            是否加粗
     */
    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);
    }


    /**
     * 增加自定义标题样式。这里用的是stackoverflow的源码
     *
     * @param docxDocument 目标文档
     * @param strStyleId   样式名称
     * @param headingLevel 样式级别
     */
    public void addCustomHeadingStyle(XWPFDocument docxDocument, String strStyleId, int headingLevel) {

        CTStyle ctStyle = CTStyle.Factory.newInstance();
        ctStyle.setStyleId(strStyleId);

        CTString styleName = CTString.Factory.newInstance();
        styleName.setVal(strStyleId);
        ctStyle.setName(styleName);

        CTDecimalNumber indentNumber = CTDecimalNumber.Factory.newInstance();
        indentNumber.setVal(BigInteger.valueOf(headingLevel));

        // lower number > style is more prominent in the formats bar
        ctStyle.setUiPriority(indentNumber);

        CTOnOff onoffnull = CTOnOff.Factory.newInstance();
        ctStyle.setUnhideWhenUsed(onoffnull);

        // style shows up in the formats bar
        ctStyle.setQFormat(onoffnull);

        // style defines a heading of the given level
        CTPPr ppr = CTPPr.Factory.newInstance();
        ppr.setOutlineLvl(indentNumber);
        ctStyle.setPPr(ppr);

        XWPFStyle style = new XWPFStyle(ctStyle);

        // is a null op if already defined
        XWPFStyles styles = docxDocument.createStyles();

        style.setType(STStyleType.PARAGRAPH);
        styles.addStyle(style);

    }

    /**
     * 设置文档中标题格式
     */
    public void setHeadingStyle(XWPFDocument document) {
        addCustomHeadingStyle(document, "标题 1", 1);
        addCustomHeadingStyle(document, "标题 2", 2);
        addCustomHeadingStyle(document, "标题 3", 3);
        addCustomHeadingStyle(document, "标题 4", 4);
        addCustomHeadingStyle(document, "标题 5", 5);
        addCustomHeadingStyle(document, "标题 6", 6);
        addCustomHeadingStyle(document, "标题 7", 7);
    }

    /**
     * 给表格添加一行数据
     *
     * @param paragraph 段落对象
     * @param row       行对象
     * @param data      不定长度的数据
     */
    public void setExcelContent(XWPFParagraph paragraph, XWPFTableRow row, String... data) {
        for (int i = 0; i < data.length; i++) {
            XWPFRun run = paragraph.createRun();
            run.setFontFamily("宋体");
            run.setText(data[i]);
            row.getCell(i).setParagraph(paragraph);
            paragraph.removeRun(0);
        }
    }


    /**
     * 添加表头标题一行数据
     *
     * @param paragraph 段落对象
     * @param row       行对象
     * @param data      不定长度的数据
     */
    public void setExcelHeadContent(XWPFParagraph paragraph, XWPFTableRow row, String... data) {
        XWPFRun run = paragraph.createRun();
        run.setFontFamily("宋体");
        run.setBold(true);
        run.setText(data[0]);
        row.getCell(0).setParagraph(paragraph);
        paragraph.removeRun(0);
        for (int i = 1; i < data.length; i++) {
            XWPFRun run1 = paragraph.createRun();
            run1.setFontFamily("宋体");
            run1.setBold(true);
            run1.setText(data[i]);
            row.addNewTableCell().setParagraph(paragraph);
            paragraph.removeRun(0);
        }
    }

    /**
     * 获取当前的日期
     *
     * @return
     */
    public String getRightNow() {
        Calendar rightNow = Calendar.getInstance();
        Integer year = rightNow.get(Calendar.YEAR);
        Integer month = rightNow.get(Calendar.MONTH) + 1;
        Integer day = rightNow.get(rightNow.DAY_OF_MONTH);
        return year + "年" + month + "月" + day + "日";
    }
}
