package com.dk.mdm.infrastructure.util;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.dk.common.exception.BaseBusinessException;
import com.dk.common.response.ResponseCodeEnum;
import com.dk.common.response.ResponseResultUtil;
import com.dk.common.response.ResponseResultVO;
import com.itextpdf.io.image.ImageDataFactory;
import com.itextpdf.kernel.font.PdfFont;
import com.itextpdf.kernel.font.PdfFontFactory;
import com.itextpdf.kernel.geom.PageSize;
import com.itextpdf.kernel.pdf.PdfDocument;
import com.itextpdf.kernel.pdf.PdfWriter;
import com.itextpdf.layout.Document;
import com.itextpdf.layout.borders.SolidBorder;
import com.itextpdf.layout.element.*;
import com.itextpdf.layout.property.HorizontalAlignment;
import com.itextpdf.layout.property.TextAlignment;
import com.itextpdf.layout.property.VerticalAlignment;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.MalformedURLException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.util.UUID;

/**
 * @author : 洪旭东
 * @desc : PdfUtil
 * @date : 2023-03-31 09:24
 */
@Component
public class PdfUtil {

    @Value("${pdf-folder}")
    private String filePath;

    public String getFilePath() {
        File dir = new File(filePath);
        if (!dir.exists()) {
            dir.mkdir();
        }

        String substring = filePath.substring(filePath.length() - 1);
        return filePath + UUID.randomUUID().toString() + substring;
    }

    /**
     * 缩放比例
     */
    private static final Float ZOOM_RATIO = 0.749f;

    /**
     * @desc : 打印PDF
     * @author : 洪旭东
     * @date : 2023-04-10 10:14
     */
    public ResponseResultVO<?> print(String printerCode, JSONObject layoutData, JSON data) {

        //创建临时文件的文件夹
        String path = getFilePath();
        File dir = new File(path);
        if (!dir.exists()) {
            dir.mkdir();
        }

        PdfWriter writer = null;
        try {
            writer = new PdfWriter(path + "test.pdf");
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        if (writer == null) {
            throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL);
        }

        //Initialize PDF document
        PdfDocument pdf = new PdfDocument(writer);

        // Initialize document
        Document document = new Document(pdf);

        //设置纸张
        //纸的高度
        Float paperHeight = setPaper(pdf, layoutData);

        //设置背景图片
        setBackGroundImage(pdf, document, layoutData);

        //处理图片
        setImage(document, layoutData, paperHeight, data, path);

        //处理文字
        if (data instanceof JSONObject) {
            setText(document, layoutData, paperHeight, (JSONObject) data);
        }

        //处理表格
        if (data instanceof JSONObject) {
            JSONArray jsonArray = new JSONArray();
            jsonArray.add(data);
            setTable(document, layoutData, paperHeight, jsonArray);
        } else if (data instanceof JSONArray) {
            setTable(document, layoutData, paperHeight, (JSONArray) data);
        }

        document.close();

        ResponseResultVO printRes = null;
        try {
            //打印
            PrintApplication.printPdf(path + "test.pdf", printerCode);
        } catch (Exception e) {
            e.printStackTrace();
            printRes = ResponseResultUtil.error(ResponseCodeEnum.OPERATE_FAIL.getCode(), e.getMessage());
        }

        deleteFolders(path);

        if (printRes!=null) {
            return printRes;
        }

        return ResponseResultUtil.success();
    }

    /**
     * @desc : 设置纸张
     * @author : 洪旭东
     * @date : 2023-04-10 08:42
     */
    private Float setPaper(PdfDocument pdf, JSONObject layoutData) {
        final String paperName = "name";

        float paperHeight;
        JSONObject paperInfo = layoutData.getJSONObject("paperInfo");
        //设置纸的类型
        if (paperInfo.getString(paperName).startsWith("A4")) {
            pdf.setDefaultPageSize(PageSize.A4);
            paperHeight = PageSize.A4.getHeight();
        } else if (paperInfo.getString(paperName).startsWith("A5")) {
            pdf.setDefaultPageSize(PageSize.A5);
            paperHeight = PageSize.A5.getHeight();
        } else if (paperInfo.getString(paperName).startsWith("B5")) {
            pdf.setDefaultPageSize(PageSize.B5);
            paperHeight = PageSize.B5.getHeight();
        } else {
            pdf.setDefaultPageSize(new PageSize(paperInfo.getFloat("width") * 28,
                    paperInfo.getFloat("height") * 28));
            paperHeight = paperInfo.getFloat("height") * 28;
//            throw new BaseBusinessException(ResponseCodeEnum.OPERATE_FAIL);
        }
        //调整纸的方向
        if ("portrait".equals(paperInfo.getString("paperDirection"))) {
            pdf.setDefaultPageSize(pdf.getDefaultPageSize().rotate());
        }

        return paperHeight;
    }

    /**
     * @desc : 设置表格
     * @author : 洪旭东
     * @date : 2023-04-07 10:36
     */
    private void setTable(Document document, JSONObject layoutData, Float paperHeight, JSONArray data) {
        JSONArray tableCol = layoutData.getJSONArray("tableCol");

        JSONObject tableInfo = layoutData.getJSONObject("tableInfo");

        if (tableCol.size() == 0) {
            return;
        }

        float[] floatArray = ArrayUtils.toPrimitive(
                tableCol.stream()
                        .filter(f -> ((JSONObject) f).getBoolean("checked"))
                        .map(m -> ((JSONObject) m).getFloat("width")).toArray(Float[]::new), 0.0F
        );

        Table table = new Table(floatArray);
        table.setWidth(tableInfo.getFloat("height"));
//        table.setHeight(50);
        table.setFixedPosition(tableInfo.getFloat("left") * ZOOM_RATIO,
                paperHeight - tableInfo.getFloat("top") * ZOOM_RATIO - tableInfo.getFloat("height") * ZOOM_RATIO,
                tableInfo.getFloat("width") * ZOOM_RATIO);
        table.setHorizontalAlignment(HorizontalAlignment.CENTER);

        for (Object it : tableCol) {
            JSONObject json = (JSONObject) it;

            if (!json.getBoolean("checked")) {
                continue;
            }

            Paragraph paragraph = new Paragraph(json.getString("title"));

            setParagraph(json, paragraph);

            Cell cell = new Cell().add(paragraph);
            table.addCell(cell);
        }

        if (data != null) {
            for (Object o : data) {
                JSONObject item = (JSONObject) o;

                for (Object it : tableCol) {
                    JSONObject json = (JSONObject) it;

                    if (!json.getBoolean("checked")) {
                        continue;
                    }

                    String value = item.getString(json.getString("title"));
                    Paragraph paragraph = new Paragraph(value != null ? value : "");

                    setParagraph(json, paragraph);

                    Cell cell = new Cell().add(paragraph);
                    table.addCell(cell);
                }
            }
        }

        document.add(table);
    }

    /**
     * @desc : 设置背景图片
     * @author : 洪旭东
     * @date : 2023-04-06 15:57
     */
    private void setBackGroundImage(PdfDocument pdf, Document document, JSONObject layoutData) {
        //背景图片
        JSONObject backgroundConfig = layoutData.getJSONObject("backgroundConfig");

        if (backgroundConfig.get("path") == null || "".equals(backgroundConfig.getString("path"))) {
            return;
        }

        Image backImage = null;
        try {
            backImage = new Image(ImageDataFactory.create(backgroundConfig.getString("path")));
        } catch (MalformedURLException e) {
            e.printStackTrace();
        }
        /* 设置图片的位置 */
        assert backImage != null;

        //全图背景
//        backImage.setFixedPosition(0, 0);
        /* 设置图片的大小 */
//        backImage.scaleAbsolute(pdf.getDefaultPageSize().getWidth(), pdf.getDefaultPageSize().getHeight());

        //图片尺寸
        Float imageHeight = backImage.getImageHeight() * ZOOM_RATIO;
        Float imageWidth = backImage.getImageWidth() * ZOOM_RATIO;
        if ("cover".equals(backgroundConfig.getString("size"))) {
            //短边完全显示
            imageWidth = pdf.getDefaultPageSize().getHeight() / imageHeight * imageWidth;
            imageHeight = pdf.getDefaultPageSize().getHeight();
        } else if ("contain".equals(backgroundConfig.getString("size"))) {
            //长边完全显示
            imageHeight = pdf.getDefaultPageSize().getWidth() / imageWidth * imageHeight;
            imageWidth = pdf.getDefaultPageSize().getWidth();
        } else if ("custom".equals(backgroundConfig.getString("size"))) {
            //自定义
            imageWidth = imageWidth * backgroundConfig.getJSONObject("customSize").getFloat("width") / 100;
            imageHeight = imageHeight * backgroundConfig.getJSONObject("customSize").getFloat("height") / 100;
        } else if ("auto".equals(backgroundConfig.getString("size"))) {
            //自动
        }
        backImage.scaleAbsolute(imageWidth, imageHeight);

        //背景位置
        if (backgroundConfig.getString("position").equals("center")) {
            backImage.setFixedPosition((pdf.getDefaultPageSize().getWidth() - imageWidth) / 2,
                    (pdf.getDefaultPageSize().getHeight() - imageHeight) / 2);
        } else if (backgroundConfig.getString("position").equals("top")) {
            backImage.setFixedPosition((pdf.getDefaultPageSize().getWidth() - imageWidth) / 2,
                    pdf.getDefaultPageSize().getHeight() - imageHeight);
        } else if (backgroundConfig.getString("position").equals("bottom")) {
            backImage.setFixedPosition((pdf.getDefaultPageSize().getWidth() - imageWidth) / 2,
                    0);
        } else if (backgroundConfig.getString("position").equals("left")) {
            backImage.setFixedPosition(0,
                    (pdf.getDefaultPageSize().getHeight() - imageHeight) / 2);
        } else if (backgroundConfig.getString("position").equals("right")) {
            backImage.setFixedPosition(pdf.getDefaultPageSize().getWidth() - imageWidth,
                    (pdf.getDefaultPageSize().getHeight() - imageHeight) / 2);
        }

//        if (backgroundConfig.getString("repeat")) {
//
//        }

        //加载图片
        document.add(backImage);
    }

    /**
     * @desc : 生成文本
     * @author : 洪旭东
     * @date : 2023-04-06 17:28
     */
    private void setText(Document document, JSONObject layoutData, Float paperHeight, JSONObject data) {

        JSONArray mainList = layoutData.getJSONArray("mainList");

        for (Object it : mainList) {
            JSONObject json = (JSONObject) it;

            if (!json.getBoolean("checked")) {
                continue;
            }

            String text = json.getString("text");
            // 文字标题宽度
            float textWidth;
            //有数据源标识
            boolean dataSourceFlag = false;
            if (json.get("dataSourceKey") == null) {
                textWidth = json.getFloat("width") * (ZOOM_RATIO - 0.15f);
            } else {
                textWidth = json.getFloat("width") * (ZOOM_RATIO) * json.getFloat("keyValueScale") / 100;
                dataSourceFlag = true;
            }

            if (dataSourceFlag) {
                Paragraph paragraph = new Paragraph(text)
                        .setHeight(json.getFloat("height") * (ZOOM_RATIO - 0.05f))
                        .setFixedPosition(json.getFloat("left") * ZOOM_RATIO,
                                paperHeight - json.getFloat("top") * ZOOM_RATIO - json.getFloat("height") * ZOOM_RATIO, textWidth);
                setParagraph(json, paragraph);
                document.add(paragraph);
                String value = data.getString(json.getString("dataSourceKey"));
                paragraph = new Paragraph(value != null ? value : "")
                        .setHeight(json.getFloat("height") * (ZOOM_RATIO - 0.05f)).setFixedPosition(json.getFloat("left") * ZOOM_RATIO + textWidth,
                                paperHeight - json.getFloat("top") * ZOOM_RATIO - json.getFloat("height") * ZOOM_RATIO,
                                json.getFloat("width") * ZOOM_RATIO * (100 - json.getFloat("keyValueScale")) / 100
                        );
                setParagraph(json, paragraph);
                document.add(paragraph);
            } else {
                Div paragraph = new Div()
                        .setHeight(json.getFloat("height") * (ZOOM_RATIO + 0.1f))
                        .setFixedPosition(json.getFloat("left") * ZOOM_RATIO,
                                paperHeight - json.getFloat("top") * ZOOM_RATIO - json.getFloat("height") * ZOOM_RATIO, textWidth);
                paragraph.add(new Paragraph(text));
                setParagraph(json, paragraph);
                paragraph.setNextRenderer(new OverflowHiddenDivRenderer(paragraph));
                document.add(paragraph);
            }
        }
    }

    /**
     * @desc : 设置段落样式
     * @author : 洪旭东
     * @date : 2023-04-07 13:03
     */
    private void setParagraph(JSONObject json, BlockElement<?> paragraph) {
        PdfFont font;
        try {
            //字体
            font = PdfFontFactory.createFont("STSong-Light", "UniGB-UCS2-H", true);
            paragraph.setFont(font);
        } catch (IOException e) {
            e.printStackTrace();
        }


//        if ("center".equals(json.getString("align1"))) {
        paragraph.setHorizontalAlignment(HorizontalAlignment.CENTER);
//        } else if ("start".equals(json.getString("align1"))) {
//            paragraph.setHorizontalAlignment(HorizontalAlignment.LEFT);
//        } else if ("end".equals(json.getString("align1"))) {
//            paragraph.setHorizontalAlignment(HorizontalAlignment.RIGHT);
//        }

        if ("center".equals(json.getString("align1"))) {
            paragraph.setTextAlignment(TextAlignment.CENTER);
        } else if ("start".equals(json.getString("align1"))) {
            paragraph.setTextAlignment(TextAlignment.LEFT);
        } else if ("end".equals(json.getString("align1"))) {
            paragraph.setTextAlignment(TextAlignment.RIGHT);
        }
        if ("center".equals(json.getString("align2"))) {
            paragraph.setVerticalAlignment(VerticalAlignment.MIDDLE);
        } else if ("start".equals(json.getString("align2"))) {
            paragraph.setVerticalAlignment(VerticalAlignment.TOP);
        } else if ("end".equals(json.getString("align2"))) {
            paragraph.setVerticalAlignment(VerticalAlignment.BOTTOM);
        }
        if (json.get("bold") != null && json.getBoolean("bold")) {
            paragraph.setBold();
        }
        if (json.get("fontSize") != null) {
            paragraph.setFontSize(json.getFloat("fontSize") * (ZOOM_RATIO - 0.18f));
        }
        if (json.get("fontStyle") != null && json.getBoolean("fontStyle")) {
            paragraph.setItalic();
        }
        if (json.get("border") != null && json.getBoolean("border")) {
            paragraph.setBorder((new SolidBorder(0.3f)));
        }
        if (json.get("line") != null && json.getBoolean("line")) {
            paragraph.setUnderline();
        }
    }

    /**
     * @desc : 生成图片
     * @author : 洪旭东
     * @date : 2023-04-06 17:30
     */
    private void setImage(Document document, JSONObject layoutData, Float paperHeight, JSON data, String path) {
        JSONArray imgList = layoutData.getJSONArray("imgList");
        for (Object it : imgList) {
            JSONObject json = (JSONObject) it;

            if ("$scanCode".equals(json.getString("name")) && data instanceof JSONObject) {
                //二维码
                String value = ((JSONObject) data).getString(json.getString("dataSourceKey"));
                json.put("path", QrCodeUtil.create(value != null ? value : "", path));
            } else if ("$barCode".equals(json.getString("name")) && data instanceof JSONObject) {
                //条形码
                String value = ((JSONObject) data).getString(json.getString("dataSourceKey"));
                json.put("path", BarCodeUtil.create(value != null ? value : "", path));
            }

            try {
                Image image = new Image(ImageDataFactory.create(json.getString("path")))
                        .setHeight(json.getFloat("height") * ZOOM_RATIO)
                        .setFixedPosition(json.getFloat("left") * ZOOM_RATIO,
                                paperHeight - json.getFloat("top") * ZOOM_RATIO - json.getFloat("height") * ZOOM_RATIO,
                                json.getFloat("width") * ZOOM_RATIO);

                document.add(image);
            } catch (MalformedURLException e) {
                e.printStackTrace();
            }
        }

    }


    /**
     * @desc : 删除文件夹
     * @author : 洪旭东
     * @date : 2023-04-11 14:45
     */
    public static void deleteFolders(String filePath) {

        Path path = Paths.get(filePath);
        try {
            Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
                @Override
                public FileVisitResult visitFile(Path file, BasicFileAttributes attributes) throws IOException {
                    Files.delete(file);
                    return FileVisitResult.CONTINUE;
                }

                @Override
                public FileVisitResult postVisitDirectory(Path dir,
                                                          IOException exc) throws IOException {
                    Files.delete(dir);
                    return FileVisitResult.CONTINUE;
                }
            });
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
