package com.casic.missiles.service.listeners.util;

import cn.afterturn.easypoi.cache.WordCache;
import cn.afterturn.easypoi.entity.ImageEntity;
import cn.afterturn.easypoi.util.PoiPublicUtil;
import cn.afterturn.easypoi.word.entity.MyXWPFDocument;
import cn.afterturn.easypoi.word.entity.params.ExcelListEntity;
import cn.afterturn.easypoi.word.parse.excel.ExcelEntityParse;
import cn.afterturn.easypoi.word.parse.excel.ExcelMapParse;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;
import java.util.stream.Collectors;

/**
 * poi  类不满足列循环格式插入，修改源码后满足
 *
 */
public class ParseWord07 {
    private static final Logger LOGGER = LoggerFactory.getLogger(cn.afterturn.easypoi.word.parse.ParseWord07.class);

    public ParseWord07() {
    }

    private void changeValues(XWPFParagraph paragraph, XWPFRun currentRun, String currentText, List<Integer> runIndex, Map<String, Object> map) throws Exception {
        if (currentText.contains("fe:") && currentText.startsWith("{{")) {
            currentText = currentText.replace("fe:", "").replace("{{", "").replace("}}", "");
            String[] keys = currentText.replaceAll("\\s{1,}", " ").trim().split(" ");
            List list = (List) PoiPublicUtil.getParamsValue(keys[0], map);
            list.forEach((objx) -> {
                if (objx instanceof ImageEntity) {
                    currentRun.setText("", 0);
                    ExcelMapParse.addAnImage((ImageEntity) objx, currentRun);
                } else {
                    PoiPublicUtil.setWordText(currentRun, objx.toString());
                }

            });
        } else {
            Object obj = PoiPublicUtil.getRealValue(currentText, map);
            if (obj instanceof ImageEntity) {
                currentRun.setText("", 0);
                ExcelMapParse.addAnImage((ImageEntity) obj, currentRun);
            } else {
                currentText = obj.toString();
                PoiPublicUtil.setWordText(currentRun, currentText);
            }
        }

        for (int k = 0; k < runIndex.size(); ++k) {
            ((XWPFRun) paragraph.getRuns().get((Integer) runIndex.get(k))).setText("", 0);
        }

        runIndex.clear();
    }

    private void checkThisTableCellIterator(List<XWPFTableCell> cells, Map<String, Object> map) throws Exception {
        int cellIndex = 0;
        while (cellIndex < cells.size()) {
            String text = cells.get(cellIndex).getText().trim();
            if (text != null && text.contains("#fe:") && text.startsWith("{{")) {
                break;
            }
            cellIndex++;
        }
        if (cellIndex >= cells.size()) {
            return;
        }
        String text = cells.get(cellIndex).getText().trim();
        if (text != null && text.contains("fe:") && text.startsWith("{{")) {
            text = text.replace("#fe:", "").replace("{{", "").replace("}}", "");
            String[] keys = text.replaceAll("\\s{1,}", " ").trim().split(" ");
            String[] parmkeys = keys[0].split("\\.");
            Object result = PoiPublicUtil.getParamsValue(keys[0], map);
            if (result instanceof List) {
                List<Map<String, String>> resultMap = (List<Map<String, String>>) result;
                List<Object> resultList = resultMap.stream().map(m -> m.get(parmkeys[parmkeys.length - 1])).collect(Collectors.toList());
                int resultIndex = 0;
                clearParagraphText((cells.get(cellIndex)).getParagraphs());
                while (resultIndex < resultList.size() && cellIndex < cells.size()) {
                    cells.get(cellIndex++).setText(String.valueOf(resultList.get(resultIndex)));
                    resultIndex++;
                }
            }
        }
    }

    private static void clearParagraphText(List<XWPFParagraph> paragraphs) {
        paragraphs.forEach((pp) -> {
            if (pp.getRuns() != null) {
                for (int i = pp.getRuns().size() - 1; i >= 0; --i) {
                    pp.removeRun(i);
                }
            }
        });
    }

    private Object checkThisTableIsNeedIterator(XWPFTableCell cell, Map<String, Object> map) throws Exception {
        String text = cell.getText().trim();
        if (text != null && text.contains("fe:") && text.startsWith("{{")) {
            text = text.replace("!fe:", "").replace("$fe:", "").replace("fe:", "").replace("{{", "");
            String[] keys = text.replaceAll("\\s{1,}", " ").trim().split(" ");
            Object result = PoiPublicUtil.getParamsValue(keys[0], map);
            return Objects.nonNull(result) ? result : new ArrayList(0);
        } else {
            return null;
        }
    }

    private void parseAllParagraph(List<XWPFParagraph> paragraphs, Map<String, Object> map) throws Exception {
        for (int i = 0; i < paragraphs.size(); ++i) {
            XWPFParagraph paragraph = (XWPFParagraph) paragraphs.get(i);
            if (paragraph.getText().indexOf("{{") != -1) {
                this.parseThisParagraph(paragraph, map);
            }
        }

    }

    private void parseThisParagraph(XWPFParagraph paragraph, Map<String, Object> map) throws Exception {
        XWPFRun currentRun = null;
        String currentText = "";
        Boolean isfinde = false;
        List<Integer> runIndex = new ArrayList();
        for (int i = 0; i < paragraph.getRuns().size(); ++i) {
            XWPFRun run = (XWPFRun) paragraph.getRuns().get(i);
            String text = run.getText(0);
            if (!StringUtils.isEmpty(text)) {
                if (isfinde) {
                    currentText = currentText + text;
                    if (currentText.indexOf("{{") == -1) {
                        isfinde = false;
                        runIndex.clear();
                    } else {
                        runIndex.add(i);
                    }

                    if (currentText.indexOf("}}") != -1) {
                        this.changeValues(paragraph, currentRun, currentText, runIndex, map);
                        currentText = "";
                        isfinde = false;
                    }
                } else if (text.indexOf("{{") >= 0) {
                    currentText = text;
                    isfinde = true;
                    currentRun = run;
                } else {
                    currentText = "";
                }

                if (currentText.indexOf("}}") != -1) {
                    this.changeValues(paragraph, currentRun, currentText, runIndex, map);
                    isfinde = false;
                }
            }
        }

    }

    private void parseThisRow(List<XWPFTableCell> cells, Map<String, Object> map) throws Exception {
        Iterator var3 = cells.iterator();

        while (var3.hasNext()) {
            XWPFTableCell cell = (XWPFTableCell) var3.next();
            this.parseAllParagraph(cell.getParagraphs(), map);
        }

    }

    private void parseThisTable(XWPFTable table, Map<String, Object> map) throws Exception {

        for (int i = 0; i < table.getNumberOfRows(); ++i) {
            XWPFTableRow row = table.getRow(i);
            List<XWPFTableCell> cells = row.getTableCells();
            //增加对该行列的检测
            checkThisTableCellIterator(cells, map);
            //检测该行的首个字母是否是
            Object listobj = this.checkThisTableIsNeedIterator((XWPFTableCell) cells.get(0), map);
            if (listobj == null) {
                this.parseThisRow(cells, map);
            } else if (listobj instanceof ExcelListEntity) {
                (new ExcelEntityParse()).parseNextRowAndAddRow(table, i, (ExcelListEntity) listobj);
                i = i + ((ExcelListEntity) listobj).getList().size() - 1;
            } else {
                ExcelMapParse.parseNextRowAndAddRow(table, i, (List) listobj);
                i = i + ((List) listobj).size() - 1;
            }
        }

    }

    public XWPFDocument parseWord(String url, Map<String, Object> map) throws Exception {
        MyXWPFDocument doc = WordCache.getXWPFDocument(url);
        this.parseWordSetValue(doc, map);
        return doc;
    }

    public XWPFDocument parseWord(String url, List<Map<String, Object>> list) throws Exception {
        if (list != null && list.size() != 0) {
            if (list.size() == 1) {
                return this.parseWord(url, (Map) list.get(0));
            } else {
                MyXWPFDocument doc = WordCache.getXWPFDocument(url);
                this.parseWordSetValue(doc, (Map) list.get(0));
                doc.createParagraph().setPageBreak(true);

                for (int i = 1; i < list.size(); ++i) {
                    MyXWPFDocument tempDoc = WordCache.getXWPFDocument(url);
                    this.parseWordSetValue(tempDoc, (Map) list.get(i));
                    tempDoc.createParagraph().setPageBreak(true);
                    doc.getDocument().addNewBody().set(tempDoc.getDocument().getBody());
                }

                return doc;
            }
        } else {
            return null;
        }
    }

    public void parseWord(XWPFDocument document, Map<String, Object> map) throws Exception {
        this.parseWordSetValue((MyXWPFDocument) document, map);
    }

    private void parseWordSetValue(MyXWPFDocument doc, Map<String, Object> map) throws Exception {
        this.parseAllParagraph(doc.getParagraphs(), map);
        this.parseHeaderAndFoot(doc, map);
        Iterator itTable = doc.getTablesIterator();
        while (itTable.hasNext()) {
            XWPFTable table = (XWPFTable) itTable.next();
            if (table.getText().indexOf("{{") != -1) {
                this.parseThisTable(table, map);
            }
        }

    }

    private void parseHeaderAndFoot(MyXWPFDocument doc, Map<String, Object> map) throws Exception {
        List<XWPFHeader> headerList = doc.getHeaderList();
        Iterator var4 = headerList.iterator();

        while (var4.hasNext()) {
            XWPFHeader xwpfHeader = (XWPFHeader) var4.next();

            for (int i = 0; i < xwpfHeader.getListParagraph().size(); ++i) {
                this.parseThisParagraph((XWPFParagraph) xwpfHeader.getListParagraph().get(i), map);
            }
        }

        List<XWPFFooter> footerList = doc.getFooterList();
        Iterator var9 = footerList.iterator();

        while (var9.hasNext()) {
            XWPFFooter xwpfFooter = (XWPFFooter) var9.next();

            for (int i = 0; i < xwpfFooter.getListParagraph().size(); ++i) {
                this.parseThisParagraph((XWPFParagraph) xwpfFooter.getListParagraph().get(i), map);
            }
        }

    }
}
