package cn.cslg.pas.service;

import cn.cslg.pas.common.model.vo.PoiVO;
import cn.cslg.pas.domain.PatentPledge;
import cn.cslg.pas.mapper.PatentPledgeMapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.RequiredArgsConstructor;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.LocaleUtil;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.impl.xb.xmlschema.SpaceAttribute;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.List;


/**
 * <p>
 * 专利信息质押质权人表 服务类
 * </p>
 *
 * @author 王岩
 * @since 2022-02-24
 */
@Service
@RequiredArgsConstructor(onConstructor_ = {@Lazy})
public class PoiService extends ServiceImpl<PatentPledgeMapper, PatentPledge> {
    public PoiVO readWordFile() throws IOException {
        PoiVO poiVO = new PoiVO();
        List<PoiVO.Pg> pgs = new ArrayList<>();
        InputStream is = new FileInputStream("C:\\\\BaiduNetdiskDownload\\\\生成\\\\first.docx");
        XWPFDocument doc = new XWPFDocument(is);
        List<IBodyElement> bodyElements = doc.getBodyElements();
        for (IBodyElement iBodyElement : bodyElements) {
            PoiVO.Pg pg = new PoiVO.Pg();
            if (iBodyElement.getElementType().name().equals("PARAGRAPH")) {
                XWPFParagraph paragraph = (XWPFParagraph) iBodyElement;
                if (paragraph.getStyle() != null && paragraph.getStyle().equals("word")) {
                    XWPFRun rh = paragraph.getRuns().get(0);
                    pg.setFontSize(rh.getFontSize());
                    pg.setFontFamily(rh.getFontFamily());
                    pg.setText(rh.getText(0));
                    pg.setColor(rh.getColor());
                    pg.setAlignment(paragraph.getFontAlignment());
                    pg.setType(paragraph.getStyle());
                    pgs.add(pg);
                } else if (paragraph.getStyle() != null && paragraph.getStyle().equals("picture")) {
                    XWPFRun rh = paragraph.getRuns().get(0);
                    pg.setAlignment(paragraph.getFontAlignment());
                    pg.setType(paragraph.getStyle());
                    XWPFPicture picture = rh.getEmbeddedPictures().get(0);
                    pg.setHeight((int) picture.getDepth());
                    pg.setWeight((int) picture.getWidth());
                    pg.setImgUrl(picture.getDescription());
                    pgs.add(pg);
                } else if (paragraph.getStyle() != null && paragraph.getStyle().contains("Heading")) {
                    XWPFRun rh = paragraph.getRuns().get(0);
                    pg.setFontSize(rh.getFontSize());
                    pg.setFontFamily(rh.getFontFamily());
                    pg.setText(rh.getText(0));
                    pg.setColor(rh.getColor());
                    pg.setAlignment(paragraph.getFontAlignment());
                    pg.setType(paragraph.getStyle());
                    pgs.add(pg);
                }

            } else if (iBodyElement.getElementType().name().equals("TABLE")) {
                XWPFTable table = (XWPFTable) iBodyElement;
                String org = table.getText().replace("\t", ",").replace("\n", "||");
                String tableText = org.replace(",||", "");
                pg.setText(tableText);
                pg.setType(table.getStyleID());
                pgs.add(pg);
            }

        }
        List<XWPFParagraph> ps = doc.getParagraphs();
        PoiVO.Pg title = new PoiVO.Pg();
        title.setAlignment(ps.get(0).getFontAlignment());
        XWPFRun r = ps.get(0).getRuns().get(0);
        title.setColor(r.getColor());
        title.setText(r.getText(0));
        title.setFontSize(r.getFontSize());

        poiVO.setPgs(pgs);
        poiVO.setTitle(title);
        return poiVO;
    }

    public void writeFile(PoiVO poiVO) throws IOException, InvalidFormatException {
        XWPFDocument doc = new XWPFDocument();// 创建Word文件
        PoiVO.Pg title = poiVO.getTitle();
        // 标题
        XWPFParagraph p = doc.createParagraph();// 新建段落
        p.setFontAlignment(title.getAlignment());// 设置段落的对齐方式
        XWPFRun r = p.createRun();//创建标题
        r.setText(title.getText());
        r.setBold(title.getBold());//设置为粗体
        r.setColor(title.getColor());//设置颜色
        r.setFontSize(title.getFontSize());//设置字体大小
        r.setStyle("Title");
        if (title.getAddCarriageReturn()) {
            r.addCarriageReturn();//回车换行
        }
        doc.createParagraph().createRun().addBreak(BreakType.PAGE);//换页

        List<PoiVO.Pg> pgs = poiVO.getPgs();

        CTSdtBlock ctSdtBlock = doc.getDocument().getBody().addNewSdt();
        this.CustomTOC(ctSdtBlock);
        doc.createParagraph().createRun().addBreak(BreakType.PAGE);//换页
        for (int i = 0; i < pgs.size(); i++) {

            if (pgs.get(i).getType() != null && pgs.get(i).getType().equals("word")) {
                XWPFParagraph tm = doc.createParagraph();
                tm.setStyle("word");
                XWPFRun rh = tm.createRun();
                rh.setFontSize(pgs.get(i).getFontSize());
                rh.setFontFamily(pgs.get(i).getFontFamily());
                rh.setText(pgs.get(i).getText());
                rh.setColor(pgs.get(i).getColor());
                tm.setFontAlignment(pgs.get(i).getAlignment());
                rh.setFontFamily(pgs.get(i).getFontFamily());
                if (pgs.get(i).getAddCarriageReturn()) {
                    rh.addCarriageReturn();//回车换行
                }
            } else if (pgs.get(i).getType() != null && pgs.get(i).getType().equals("picture")) {
                XWPFParagraph pImg = doc.createParagraph();
                pImg.setStyle("picture");
                pImg.setFontAlignment(pgs.get(i).getAlignment());
                XWPFRun rImg = pImg.createRun();//创建标题
                rImg.addCarriageReturn();//回车换行
                String imgData = pgs.get(i).getImgUrl();
                // 转为数据流
                InputStream stream = new FileInputStream(imgData);
                // 向段落中插入图片
                rImg.addPicture(stream, Document.PICTURE_TYPE_PNG, pgs.get(i).getImgUrl(), Units.toEMU(pgs.get(i).getWeight()), Units.toEMU(pgs.get(i).getHeight()));
            } else if (pgs.get(i).getType() != null && pgs.get(i).getType().equals("table")) {
                String org = pgs.get(i).getText();
                int rows;
                int cols = 0;
                String[] row = org.split("\\|\\|");
                rows = row.length;
                for (String s : row) {
                    String[] tem = s.split(",");
                    cols = Math.max(cols, tem.length);
                }

                XWPFTable table1 = doc.createTable(rows, cols);
                table1.setStyleID(pgs.get(i).getType());
                table1.setWidthType(TableWidthType.AUTO);
                for (int t = 0; t < row.length; t++) {
                    String[] tem = row[t].split(",");
                    XWPFTableRow row1 = table1.getRow(t);
                    for (int q = 0; q < tem.length; q++) {
                        row1.getCell(q).setText(tem[q]);
                    }

                }
                doc.setTable(0, table1);

            } else if (pgs.get(i).getType().contains("Heading")) {
                XWPFParagraph Paragraph = doc.createParagraph();
                CTBookmark ctBookmark1 = Paragraph.getCTP().addNewBookmarkStart();//开始书签
                ctBookmark1.setId(BigInteger.valueOf(i));//开始书签和结束书签通过ID关联
                ctBookmark1.setName("书签" + i);//书签名称
                Paragraph.setStyle(pgs.get(i).getType());
                XWPFRun run1 = Paragraph.createRun();
                run1.setText(pgs.get(i).getText());
                run1.setColor(pgs.get(i).getColor());
                run1.setFontSize(pgs.get(i).getFontSize());
                run1.setBold(true);
                Paragraph.getCTP().addNewBookmarkEnd().setId(BigInteger.valueOf(i));
            }
        }
        this.addItem2TOC(doc, ctSdtBlock);
        Integer pageCount = doc.getProperties().getExtendedProperties().getUnderlyingProperties().getPages();
        FileOutputStream out = new FileOutputStream("C:\\\\BaiduNetdiskDownload\\\\生成\\\\first.docx");
        CTSectPr sectPr = doc.getDocument().getBody().addNewSectPr();
        XWPFHeaderFooterPolicy policy = new XWPFHeaderFooterPolicy(doc, sectPr);


//        this.createDefaultFooter(doc,"宋体",8);
        //  添加页脚,
        CTP ctpFooter = CTP.Factory.newInstance();
        CTR ctrFooter = ctpFooter.addNewR();
        CTText ctFooter = ctrFooter.addNewT();
        String footerText = "ctpFooter";
        ctFooter.setStringValue(footerText);
        XWPFParagraph footerParagraph = new XWPFParagraph(ctpFooter, doc);
        XWPFParagraph[] parsFooter = new XWPFParagraph[1];
        parsFooter[0] = footerParagraph;
        policy.createFooter(XWPFHeaderFooterPolicy.DEFAULT, parsFooter);
        doc.write(out);
        out.close();

        System.out.println("Process Completed Successfully");

    }


    public void addItem2TOC(XWPFDocument doc, CTSdtBlock block) {
        List<XWPFParagraph> paragraphs = doc.getParagraphs();
        int num = 1;
        for (XWPFParagraph par : paragraphs) {
            String parStyle = par.getStyle();
            List<CTR> ctrlist = par.getCTP().getRList();//获取<w:p>标签下的<w:r>list
            for (CTR r : ctrlist) {  //遍历r
                List<CTEmpty> breaklist = r.getLastRenderedPageBreakList();//判断是否存在此标签
                if (breaklist.size() > 0) {
                    num++; //页数添加
                }
            }
            if (parStyle != null && parStyle.startsWith("Heading")) {
                List<CTBookmark> bookmarkList = par.getCTP().getBookmarkStartList();
                try {
                    int level = Integer.parseInt(parStyle.substring("Heading".length()));

                    //添加标题
                    this.addRow(level, par.getText(), num, bookmarkList.get(0).getName(), block);
                } catch (NumberFormatException e) {
                    e.printStackTrace();
                }
            }
        }
    }


    //生成页脚
    public static void createDefaultFooter(final XWPFDocument document, String fontName, int fontSize) throws IOException {
        CTP pageNo = CTP.Factory.newInstance();
        XWPFParagraph footer = new XWPFParagraph(pageNo, document);
        footer.createRun().setFontSize(2000);
        CTPPr begin = pageNo.addNewPPr();
        begin.addNewPStyle().setVal("style21");
        begin.addNewJc().setVal(STJc.CENTER);
        CTR pageBegin = pageNo.addNewR();
        pageBegin.addNewRPr().addNewRFonts().setAscii(fontName);
        pageBegin.addNewRPr().addNewRFonts().setCs(fontName);
        pageBegin.addNewRPr().addNewRFonts().setEastAsia(fontName);
        pageBegin.addNewRPr().addNewRFonts().setHAnsi(fontName);
        pageBegin.addNewRPr().addNewSz().setVal(BigInteger.valueOf(fontSize));
        pageBegin.addNewRPr().addNewSzCs().setVal(BigInteger.valueOf(fontSize));
        pageBegin.addNewFldChar().setFldCharType(STFldCharType.BEGIN);
        CTR page = pageNo.addNewR();
        page.addNewRPr().addNewRFonts().setAscii(fontName);
        page.addNewRPr().addNewRFonts().setCs(fontName);
        page.addNewRPr().addNewRFonts().setEastAsia(fontName);
        page.addNewRPr().addNewRFonts().setHAnsi(fontName);
        page.addNewRPr().addNewSz().setVal(BigInteger.valueOf(fontSize));
        page.addNewRPr().addNewSzCs().setVal(BigInteger.valueOf(fontSize));
        page.addNewInstrText().setStringValue("PAGE   \\* MERGEFORMAT");
        CTR pageSep = pageNo.addNewR();
        pageSep.addNewRPr().addNewRFonts().setAscii(fontName);
        pageSep.addNewRPr().addNewRFonts().setCs(fontName);
        pageSep.addNewRPr().addNewRFonts().setEastAsia(fontName);
        pageSep.addNewRPr().addNewRFonts().setHAnsi(fontName);
        pageSep.addNewRPr().addNewSz().setVal(BigInteger.valueOf(fontSize));
        pageSep.addNewRPr().addNewSzCs().setVal(BigInteger.valueOf(fontSize));
        pageSep.addNewFldChar().setFldCharType(STFldCharType.SEPARATE);
        CTR end = pageNo.addNewR();
        CTRPr endRPr = end.addNewRPr();
        endRPr.addNewNoProof();
        endRPr.addNewLang().setVal("zh-CN");
        end.addNewRPr().addNewRFonts().setAscii(fontName);
        end.addNewRPr().addNewRFonts().setCs(fontName);
        end.addNewRPr().addNewRFonts().setEastAsia(fontName);
        end.addNewRPr().addNewRFonts().setHAnsi(fontName);
        end.addNewRPr().addNewSz().setVal(BigInteger.valueOf(fontSize));
        end.addNewRPr().addNewSzCs().setVal(BigInteger.valueOf(fontSize));
        end.addNewFldChar().setFldCharType(STFldCharType.END);

        CTSectPr sectPr = document.getDocument().getBody().isSetSectPr() ? document.getDocument().getBody().getSectPr() : document.getDocument().getBody().addNewSectPr();
        XWPFHeaderFooterPolicy policy = new XWPFHeaderFooterPolicy(document, sectPr);
        policy.createFooter(STHdrFtr.DEFAULT, new XWPFParagraph[]{footer});
    }

    // 目录添加行
    public void addRow(int level, String title, int page, String bookmarkRef, CTSdtBlock block) {
        CTSdtContentBlock contentBlock = block.getSdtContent();
        CTP p = contentBlock.addNewP();
        p.setRsidR("00EF7E24".getBytes(LocaleUtil.CHARSET_1252));
        p.setRsidRDefault("00EF7E24".getBytes(LocaleUtil.CHARSET_1252));
        CTPPr pPr = p.addNewPPr();
        pPr.addNewPStyle().setVal("TOC" + level);
        CTTabs tabs = pPr.addNewTabs();//Set of Custom Tab Stops自定义制表符集合
        CTTabStop tab = tabs.addNewTab();//Custom Tab Stop自定义制表符
        tab.setVal(STTabJc.RIGHT);
        tab.setLeader(STTabTlc.DOT);
        tab.setPos(new BigInteger("9100"));//默认为8290，因为调整过页边距，所有需要调整，手动设置找出最佳值
        pPr.addNewRPr().addNewNoProof();//不检查语法
        CTR run = p.addNewR();
        run.addNewRPr().addNewNoProof();
        for (int i = 0; i < level; i++) {
            title = "\n" + title;
        }
        run.addNewT().setStringValue(title);//添加标题文字
        //设置标题字体
        CTRPr pRpr = run.getRPr();
        CTFonts fonts = pRpr.isSetRFonts() ? pRpr.getRFonts() : pRpr.addNewRFonts();
        fonts.setAscii("Times New Roman");
        fonts.setEastAsia("楷体");
        fonts.setHAnsi("楷体");
        // 设置标题字体大小
        CTHpsMeasure sz = pRpr.isSetSz() ? pRpr.getSz() : pRpr.addNewSz();
        sz.setVal(new BigInteger("21"));
        CTHpsMeasure szCs = pRpr.isSetSzCs() ? pRpr.getSzCs() : pRpr.addNewSzCs();
        szCs.setVal(new BigInteger("21"));
        //添加制表符
        run = p.addNewR();
        run.addNewRPr().addNewNoProof();
        run.addNewTab();
        //添加页码左括号
        p.addNewR().addNewT().setStringValue("(");
        //STFldCharType.BEGIN标识与结尾处STFldCharType.END相对应
        run = p.addNewR();
        run.addNewRPr().addNewNoProof();
        run.addNewFldChar().setFldCharType(STFldCharType.BEGIN);//Field Character Type
        // pageref run
        run = p.addNewR();
        run.addNewRPr().addNewNoProof();
        CTText text = run.addNewInstrText();//Field Code 添加域代码文本控件
        text.setSpace(SpaceAttribute.Space.PRESERVE);
        // bookmark reference
        //源码的域名为" PAGEREF _Toc","\h"含义为在目录内建立目录项与页码的超链接
        text.setStringValue(" PAGEREF " + bookmarkRef + " \\h ");
        p.addNewR().addNewRPr().addNewNoProof();
        run = p.addNewR();
        run.addNewRPr().addNewNoProof();
        run.addNewFldChar().setFldCharType(STFldCharType.SEPARATE);
        // page number run
        run = p.addNewR();
        run.addNewRPr().addNewNoProof();
        run.addNewT().setStringValue(Integer.toString(page));
        run = p.addNewR();
        run.addNewRPr().addNewNoProof();
        //STFldCharType.END标识与上面STFldCharType.BEGIN相对应
        run.addNewFldChar().setFldCharType(STFldCharType.END);
        //添加页码右括号
        p.addNewR().addNewT().setStringValue(")");
        //设置行间距
        CTSpacing pSpacing = pPr.getSpacing() != null ? pPr.getSpacing() : pPr.addNewSpacing();
        pSpacing.setLineRule(STLineSpacingRule.AUTO);//行间距类型：多倍
        pSpacing.setLine(new BigInteger("360"));//此处1.5倍行间距
    }

    //添加目录
    public void CustomTOC(CTSdtBlock block) {
        CTSdtPr sdtPr = block.addNewSdtPr();
        CTDecimalNumber id = sdtPr.addNewId();
        id.setVal(new BigInteger("4844945"));
        sdtPr.addNewDocPartObj().addNewDocPartGallery().setVal("Table of contents");
        CTSdtEndPr sdtEndPr = block.addNewSdtEndPr();
        CTRPr rPr = sdtEndPr.addNewRPr();
        CTFonts fonts = rPr.addNewRFonts();
        fonts.setAsciiTheme(STTheme.MINOR_H_ANSI);
        fonts.setEastAsiaTheme(STTheme.MINOR_H_ANSI);
        fonts.setHAnsiTheme(STTheme.MINOR_H_ANSI);
        fonts.setCstheme(STTheme.MINOR_BIDI);
        rPr.addNewB().setVal(STOnOff.OFF);
        rPr.addNewBCs().setVal(STOnOff.OFF);
        rPr.addNewColor().setVal("auto");
        rPr.addNewSz().setVal(new BigInteger("24"));
        rPr.addNewSzCs().setVal(new BigInteger("24"));
        CTSdtContentBlock content = block.addNewSdtContent();
        CTP p = content.addNewP();
        p.setRsidR("00EF7E24".getBytes(LocaleUtil.CHARSET_1252));
        p.setRsidRDefault("00EF7E24".getBytes(LocaleUtil.CHARSET_1252));
        p.addNewPPr().addNewPStyle().setVal("TOCHeading");
        p.addNewR().addNewT().setStringValue("目     录");//源码中为"Table of contents"
        //设置段落对齐方式，即将“目录”二字居中
        CTPPr pr = p.getPPr();
        CTJc jc = pr.isSetJc() ? pr.getJc() : pr.addNewJc();
        STJc.Enum en = STJc.Enum.forInt(ParagraphAlignment.CENTER.getValue());
        jc.setVal(en);
        //"目录"二字的字体
        CTRPr pRpr = p.getRArray(0).addNewRPr();
        fonts = pRpr.isSetRFonts() ? pRpr.getRFonts() : pRpr.addNewRFonts();
        fonts.setAscii("Times New Roman");
        fonts.setEastAsia("华文中宋");
        fonts.setHAnsi("华文中宋");
        //"目录"二字加粗
        CTOnOff bold = pRpr.isSetB() ? pRpr.getB() : pRpr.addNewB();
        bold.setVal(STOnOff.TRUE);
        // 设置“目录”二字字体大小为24号
        CTHpsMeasure sz = pRpr.isSetSz() ? pRpr.getSz() : pRpr.addNewSz();
        sz.setVal(new BigInteger("36"));
    }


}
