package com.ruoyi.common.utils;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;

import java.io.IOException;
import java.io.OutputStream;
import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * PDF写入器
 * @author gxk
 */
public class PdfBaseWriter extends Document{

    // ---------------------------------默认参数---------------------------------
    /**
     * 中文字体
     */
    public final String FONT_NAME_ST_SONG_LIGHT = "STSong-Light";
    /**
     * 中文字体编码
     */
    public final String FONT_ENCODING_UNI_GB_UCS2_H = "UniGB-UCS2-H";

    //---------------------------------常用字体/颜色---------------------------------
    /**
     * 灰色
     */
    public final BaseColor GREY_COLOR = new BaseColor(139, 134, 130);
    /**
     * 浅黄色
     */
    public final BaseColor LIGHT_YELLOW_COLOR = new BaseColor(255, 255, 153);

    /**
     * 灰色
     */
    public final BaseColor LIGHT_GRAY_COLOR = new BaseColor(241, 241, 241);
    /**
     * 浅蓝色
     */
    public final BaseColor LIGHT_BLUE_COLOR = new BaseColor(133, 188, 224);
    /**
     * 深蓝色
     */
    public final BaseColor HARD_BLUE_COLOR = new BaseColor(31, 86, 112);

    /**
     * 创建页面大小为A4的PDF
     * @param os PDF写入流
     * @throws DocumentException
     */
    public PdfBaseWriter(OutputStream os) throws DocumentException {
        super();
        PdfWriter.getInstance(this, os);
    }

    /**
     * 创建PDF
     * @param os PDF写入流
     * @param pageSize 页面大小(PageSize.A4等)
     * @throws DocumentException
     */
    public PdfBaseWriter(OutputStream os, Rectangle pageSize) throws DocumentException {
        super(pageSize);
        PdfWriter.getInstance(this, os);
    }

    //------------------------------------表------------------------------------
    /**
     * 写入表格,表格数据集合中第一行数据 key 为表格表头
     * @param rows 表格数据集合
     * @return 表格 {@link PdfPTable}
     */
    public PdfPTable writeTable(ArrayList<LinkedHashMap<String, Object>> rows) {
        if (rows == null) {
            return null;
        }
        // 根据写入数据宽度创建表格
        List<String> headers = new ArrayList<String>(rows.get(0).keySet());
        PdfPTable table = createWithHeaderTable(headers, null);

        for (LinkedHashMap<String, Object> row : rows) {
            for (String k : headers) {
                String text = String.valueOf(row.get(k));
                writeCell(String.valueOf(text), calculateColumnNumber(k), 1, table);
            }
        }
        addContent(table);
        return table;
    }
    /**
     * 创建带表头的表格 {@link PdfPTable}
     * @param headers 表头数据集
     * @param columnWidths 每一列的宽度
     * @return 表格 {@link PdfPTable}
     */
    public PdfPTable createWithHeaderTable(List<String> headers, float[] columnWidths) {
        PdfPTable headerTable = null;
        if (columnWidths == null) {
            int numColumns = calculateColumnNumber(headers);
            headerTable = new PdfPTable(numColumns);
        } else {
            headerTable = new PdfPTable(columnWidths);
        }
        headerTable.setWidthPercentage(100);
        headerTable.setSpacingBefore(10);
        for (String text : headers) {
            if (columnWidths == null) {
                writeCell(text, Element.ALIGN_CENTER, calculateColumnNumber(text), 1, headerTable, defaultFont(), 0f, Rectangle.BOX, LIGHT_BLUE_COLOR);
            } else {
                writeCell(text, Element.ALIGN_CENTER, 1, 1, headerTable, defaultFont(), 0f, Rectangle.BOX, LIGHT_GRAY_COLOR);
            }
        }
        return headerTable;
    }

    /**
     * 设置空白行
     * @param table 表 {@link PdfPTable}
     * @param bgColor 背景颜色 {@link BaseColor}
     * @param columnNumber 列号
     * @param fixedHeight 固定高度
     */
    public void setBlankRow(PdfPTable table, BaseColor bgColor, int columnNumber, float fixedHeight) {
        Paragraph paragraph = new Paragraph("");
        PdfPCell pdfPCell = newPdfPCell(bgColor, 0, 1, columnNumber, 1, paragraph);
        // 单元格固定高度
        pdfPCell.setFixedHeight(fixedHeight);
        table.addCell(pdfPCell);
    }

    //------------------------------------单元格------------------------------------
    /**
     * 写入无边框单元格 {@link PdfPCell}
     * @param text 内容
     * @param align 对齐方式 {@link Element}
     * @param colspan 所占列数
     * @param rowspan 所占行数
     * @param table 表 {@link PdfPTable}
     * @return 单元格 {@link PdfPCell}
     */
    public PdfPCell writeNoBorderCell(String text, int align, int colspan, int rowspan, PdfPTable table) {
        return writeCell(text, align, colspan, rowspan, table, defaultFont(), 0f, Rectangle.NO_BORDER, BaseColor.WHITE);
    }

    /**
     * 写入单元格 {@link PdfPCell}
     * @param text 内容
     * @param colspan 所占列数
     * @param rowspan 所占行数
     * @param table 表 {@link PdfPTable}
     * @return 单元格 {@link PdfPCell}
     */
    public PdfPCell writeCell(String text, int colspan, int rowspan, PdfPTable table) {
        return writeCell(text, Element.ALIGN_CENTER, colspan, rowspan, table, defaultFont(), 0f, Rectangle.BOX, BaseColor.WHITE);
    }

    /**
     * 写入单元格 {@link PdfPCell}
     * @param text 内容
     * @param align 对齐方式
     * @param colspan 所占列数
     * @param rowspan 所占行数
     * @param table 表 {@link PdfPTable}
     * @return 单元格 {@link PdfPCell}
     */
    public PdfPCell writeCell(String text, int align, int colspan, int rowspan, PdfPTable table) {
        return writeCell(text, align, colspan, rowspan, table, defaultFont(), 0f, Rectangle.BOX, BaseColor.WHITE);
    }

    /**
     * 写入单元格 {@link PdfPCell}
     * @param text 内容
     * @param align 对齐方式
     * @param colspan 所占列数
     * @param rowspan 所占行数
     * @param table 表 {@link PdfPTable}
     * @return 单元格 {@link PdfPCell}
     */
    public PdfPCell writeBottomCell(String text, int align, int colspan, int rowspan, PdfPTable table) {
        return writeCell(text, align, colspan, rowspan, table, defaultFont(), 0f, Rectangle.BOTTOM, BaseColor.WHITE);
    }

    /**
     * 写入单元格 {@link PdfPCell}
     * @param text 内容
     * @param align 对齐方式 {@link Element}
     * @param colspan 所占列数
     * @param rowspan 所占行数
     * @param table 表 {@link PdfPTable}
     * @param font 字体 {@link Font}
     * @return 单元格 {@link PdfPCell}
     */
    public PdfPCell writeCell(String text, int align, int colspan, int rowspan, PdfPTable table, Font font) {
        return writeCell(text, align, colspan, rowspan, table, font, 0f, Rectangle.BOX);
    }

    /**
     * 写入单元格 {@link PdfPCell}
     * @param text 内容
     * @param align 对齐方式 {@link Element}
     * @param colspan 所占列数
     * @param rowspan 所占行数
     * @param table 表 {@link PdfPTable}
     * @param font 字体 {@link Font}
     * @param paddingLeft 左边距
     * @param border 边框 {@link Rectangle}
     * @return 单元格 {@link PdfPCell}
     */
    public PdfPCell writeCell(String text, int align, int colspan, int rowspan, PdfPTable table, Font font, Float paddingLeft, int border) {
        return writeCell(text, align, colspan, rowspan, table, font, paddingLeft, border, true, BaseColor.WHITE);
    }

    /**
     * 写入单元格 {@link PdfPCell}
     * @param text 内容
     * @param align 对齐方式 {@link Element}
     * @param colspan 所占列数
     * @param rowspan 所占行数
     * @param table 表 {@link PdfPTable}
     * @param font 字体 {@link Font}
     * @param paddingLeft 左边距
     * @param border 边框 {@link Rectangle}
     * @param bgColor 背景颜色 {@link BaseColor}
     * @return 单元格 {@link PdfPCell}
     */
    public PdfPCell writeCell(String text, int align, int colspan, int rowspan, PdfPTable table, Font font, Float paddingLeft, int border, BaseColor bgColor) {
        return writeCell(text, align, colspan, rowspan, table, font, paddingLeft, border, true, bgColor);
    }

    /**
     * 写入单元格 {@link PdfPCell}
     * @param text 内容
     * @param align 对齐方式 {@link Element}
     * @param colspan 所占列数
     * @param rowspan 所占行数
     * @param table 表 {@link PdfPTable}
     * @param font 字体 {@link Font}
     * @param paddingLeft 左边距
     * @param border 边框 {@link Rectangle}
     * @param isSet 是否已经设置
     * @param bgColor 背景颜色 {@link BaseColor}
     * @return 单元格 {@link PdfPCell}
     */
    public PdfPCell writeCell(String text, int align, int colspan, int rowspan, PdfPTable table, Font font, Float paddingLeft, int border, boolean isSet, BaseColor bgColor) {
        if (text == null) {
            text = "";
        }

        // 包含中文,则使用中文字体
        if (isChinese(text)) {
            font = chineseFont(font.getSize(), font.getStyle(), font.getColor());
        }
        Paragraph elements = new Paragraph(text, font);
        elements.setAlignment(align);

        PdfPCell cell = newPdfPCell(bgColor, border, align, colspan, rowspan, elements);
        if (paddingLeft != null) {
            cell.setPaddingLeft(paddingLeft);
        }
        if (align == Element.ALIGN_LEFT) {
            cell.setPaddingLeft(4);
        }
        cell.setPaddingBottom(10);
        if (isSet) {
            table.addCell(cell);
        }
        return cell;
    }

    /**
     * 创建新的单元格 {@link PdfPCell}
     * @param bgColor 背景颜色 {@link BaseColor}
     * @param border 边框 {@link Rectangle}
     * @param align 对齐方式 {@link Element}
     * @param colspan 所占列数
     * @param rowspan 所占行数
     * @param paragraph 段落 {@link Paragraph}
     * @return 单元格 {@link PdfPCell}
     */
    public PdfPCell newPdfPCell(BaseColor bgColor, int border, int align, int colspan, int rowspan, Paragraph paragraph) {
        PdfPCell cell = new PdfPCell();
        cell.setBorderColor(BaseColor.BLACK);
        cell.setBorderColorLeft(BaseColor.BLACK);
        cell.setBorderColorRight(BaseColor.BLACK);
        cell.setBackgroundColor(bgColor);
        cell.setBorder(border);
        // 水平居中
        cell.setHorizontalAlignment(align);
        // 垂直居中
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setColspan(colspan);
        cell.setRowspan(rowspan);
        cell.setMinimumHeight(10);
        cell.addElement(paragraph);
        // 设置单元格的边框宽度和颜色
        cell.setBorderWidth(0.5f);
        cell.setBorderColor(GREY_COLOR);
        return cell;
    }
    /**
     * 创建内容为图片的单元格 {@link PdfPCell}
     * @param colspan 所占列数
     * @param rowspan 所占行数
     * @param image 内容(文字或图片对象) {@link Image}
     * @param fitWidth 宽度自适应
     * @param fitHeight 高度自适应
     * @return 单元格 {@link PdfPCell}
     */
    public PdfPCell newPdfPCellOfImage(int colspan, int rowspan, Image image, float fitWidth, float fitHeight) {
        PdfPCell cell = new PdfPCell();
        cell.setUseAscender(Boolean.TRUE);
        cell.setVerticalAlignment(PdfPCell.ALIGN_MIDDLE);
        cell.setBorder(Rectangle.BOX);
        cell.setBorderColor(BaseColor.GRAY);
        cell.setBackgroundColor(BaseColor.WHITE);
        cell.setColspan(colspan);
        cell.setRowspan(rowspan);
        image.scaleToFit(fitWidth, fitHeight);
        cell.addElement(image);
        return cell;
    }

    /**
     * 把图文混合写入单元格
     * @param list
     * @param table
     * @return
     */
    public PdfPCell writeTextAndImageCell(List<String> list, PdfPTable table) throws DocumentException, IOException {
        PdfPCell cell = new PdfPCell();
        cell.setBorderColor(BaseColor.GRAY);
        for (String value : list) {
            if (value.contains("/") && (value.endsWith(".jpg") || value.endsWith(".png") || value.endsWith(".jpeg"))) {
                Image image = Image.getInstance(value);
                cell.addElement(image);
            } else {
                cell.addElement(createTextInImageCell(value));
            }
        }
        table.addCell(cell);
        return cell;
    }

    //------------------------------------文本内容------------------------------------

    /**
     * 设置一级标题
     * @param title 章节标题
     * @param number 章节编号
     * @return 返回当前标题 {@link Chapter}
     */
    public Chapter setTitle1(String title, int number) {
        Paragraph paragraph = getParagraph(2, title);
        Chapter chapter = new Chapter(paragraph, number);
        chapter.setTriggerNewPage(false);
        addContent(chapter);
        return chapter;
    }

    /**
     * 设置二级标题
     * @param chapter 对应一级标题 {@link Chapter}
     * @param title 章节标题
     * @return 返回当前标题 {@link Section}
     */
    public Section setTitle2(Chapter chapter, String title) {
        Paragraph paragraph = getParagraph(3, title);
        Section section = chapter.addSection(paragraph);
        section.setNumberStyle(Section.NUMBERSTYLE_DOTTED_WITHOUT_FINAL_DOT);
        addContent(section);
        return section;
    }

    /**
     * 设置三级标题
     * @param section 对应二级标题 {@link Section}
     * @param title 章节标题
     */
    public void setTitle3(Section section, String title) {
        Paragraph paragraph = getParagraph(4, title);
        Section subsection = section.addSection(paragraph);
        subsection.setNumberStyle(Section.NUMBERSTYLE_DOTTED);
        addContent(subsection);
    }

    /**
     * 写出段落正文
     * @param text 正文内容
     */
    public void writeText(String text) {
        writeText(text, defaultFont(), true);
    }

    /**
     * 写出段落正文
     * @param text 正文内容
     * @param font 字体 {@link Font}
     */
    public void writeText(String text, Font font) {
        writeText(text, font, true);
    }

    /**
     * 写出段落正文
     * @param text 正文内容
     * @param font 字体 {@link Font}
     * @param firstLineIndent 首行是否需要缩进
     */
    public void writeText(String text, Font font, boolean firstLineIndent) {
        Paragraph paragraph = new Paragraph(text, font);
        if (firstLineIndent) {
            paragraph.setFirstLineIndent(24);
        }
        addContent(paragraph);
    }


    /**
     * 写出段落正文
     * @param text 正文内容
     * @param font 字体 {@link Font}
     * @param alignment 设置此段落的对齐方式 {@link Element}
     */
    public void writeText(String text, Font font, int alignment) {
        Paragraph paragraph = new Paragraph(text, font);
        paragraph.setAlignment(alignment);
        addContent(paragraph);
    }

    /**
     * 写出列表
     * @param texts 列表内容集合
     * @param wantNumbering 是否需要序号
     */
    public void writeList(List<String> texts, boolean wantNumbering) {
        if (texts == null || texts.size() == 0) {
            return;
        }
        int i = 1;
        for (String text : texts) {
            if (wantNumbering) {
                writeText(i + "、" + text, defaultFont(), false);
            }else {
                writeText(text, defaultFont(), false);
            }
            i++;
        }
    }

    /**
     * 写出列表
     * @param formData 列表内容集合
     * @param tagValue value 值是否需要下划线
     */
    public void writeList(Map<String, String> formData, boolean tagValue) {
        if (formData == null || formData.size() == 0) {
            return;
        }

        for (String v : formData.keySet()) {
            addContent(new Phrase(v + ":", defaultFont()));

            Phrase phrase = new Phrase();
            Chunk chunk = new Chunk(formData.get(v), defaultFont());
            if (tagValue) {
                chunk.setUnderline(0.2f, -2f);
            }
            phrase.add(chunk);

            addContent(phrase);
            addContent(Chunk.NEWLINE);
        }
    }

    /**
     * 添加key-value似的内容
     * @param frontText 前内容
     * @param behindText 后内容
     * @param size 大小
     * @param firstLineIndent 第一行缩进
     * @param spacingAfter 段间距
     */
    public void writeUnderlineText(String frontText, String behindText, Float size, int firstLineIndent, Float spacingAfter) {
        Paragraph paragraph = new Paragraph();
        paragraph.setFirstLineIndent(firstLineIndent);
        paragraph.setSpacingAfter(spacingAfter);
        Phrase frontPhrase = new Phrase(frontText, defaultFont(size));
        Phrase behindPhrase = new Phrase();
        Chunk chunk = new Chunk(behindText, defaultFont(size));
        chunk.setUnderline(01.f, -5f);
        behindPhrase.add(chunk);
        paragraph.add(frontPhrase);
        paragraph.add(behindPhrase);
        addContent(paragraph);
    }

//    /**
//     * 标题
//     * @param content
//     * @return
//     * @throws IOException
//     * @throws DocumentException
//     */
//    public static Paragraph createTitle(String content) throws IOException, DocumentException {
//        Font font = new Font(getBaseFont(), 24, Font.BOLD);
//        Paragraph paragraph = new Paragraph(content, font);
//        paragraph.setAlignment(Element.ALIGN_CENTER);
//        return paragraph;
//    }
//
//    /**
//     * H1标题
//     * @param content
//     * @return
//     * @throws IOException
//     * @throws DocumentException
//     */
//    public static Paragraph createChapterH1(String content) throws IOException, DocumentException {
//        Font font = new Font(getBaseFont(), 22, Font.BOLD);
//        Paragraph paragraph = new Paragraph(content, font);
//        paragraph.setAlignment(Element.ALIGN_LEFT);
//        return paragraph;
//    }
//
//    /**
//     * H2标题
//     * @param content
//     * @return
//     * @throws IOException
//     * @throws DocumentException
//     */
//    public static Paragraph createChapterH2(String content) throws IOException, DocumentException {
//        Font font = new Font(getBaseFont(), 18, Font.BOLD);
//        Paragraph paragraph = new Paragraph(content, font);
//        paragraph.setAlignment(Element.ALIGN_LEFT);
//        // 设置段落上空白
//        paragraph.setSpacingAfter(5f);
//        return paragraph;
//    }
//
//    /**
//     * 段
//     * @param content
//     * @return
//     * @throws IOException
//     * @throws DocumentException
//     */
//    public static Paragraph createParagraph(String content) throws IOException, DocumentException {
//        Paragraph paragraph = new Paragraph(content, defaultFont());
//        paragraph.setAlignment(Element.ALIGN_LEFT);
//        // 设置左缩进
//        paragraph.setIndentationLeft(12);
//        // 设置右缩进
//        paragraph.setIndentationRight(12);
//        // 设置首行缩进
//        paragraph.setFirstLineIndent(24);
//        // 行间距
//        paragraph.setLeading(20f);
//        // 设置段落上空白
//        paragraph.setSpacingBefore(5f);
//        // 设置段落下空白
//        paragraph.setSpacingAfter(10f);
//        return paragraph;
//    }

    /**
     * 创建文本
     * @param type 1-标题 2-标题一 3-标题二 4-标题三 5-正文 6-正文左对齐
     */
    public Paragraph getParagraph(int type, String text) {
        Font font = new Font(defaultFont());
        if (1 == type) {
            font.setSize(22f);
            font.setStyle(Font.BOLD);
        } else if(2 == type) {
            font.setSize(16f);
            font.setStyle(Font.BOLD);
        } else if(3 == type) {
            font.setSize(14f);
            font.setStyle(Font.BOLD);
        } else if(4 == type) {
            font.setSize(14f);
        } else if(5 == type) {
            font.setSize(10.5f);
        } else if(6 == type) {
            font.setSize(10.5f);
        } else {
            font.setSize(10.5f);
        }

        Paragraph paragraph = new Paragraph(text, font);
        if (1 == type) {
            paragraph.setAlignment(Paragraph.ALIGN_CENTER);
            paragraph.setSpacingBefore(10f);
            paragraph.setSpacingAfter(10f);
        } else if(2 == type) {
            paragraph.setAlignment(Element.ALIGN_JUSTIFIED);
            paragraph.setSpacingBefore(2f);
            paragraph.setSpacingAfter(2f);
        } else if(3 == type){
            paragraph.setSpacingBefore(2f);
            paragraph.setSpacingAfter(1f);
        } else if(4 == type){
            paragraph.setSpacingBefore(2f);
            paragraph.setSpacingAfter(2f);
        } else if(5 == type){
            paragraph.setAlignment(Element.ALIGN_JUSTIFIED);
            paragraph.setFirstLineIndent(24);
            paragraph.setSpacingBefore(1f);
            paragraph.setSpacingAfter(1f);
        } else if(6 == type){
            paragraph.setAlignment(Element.ALIGN_LEFT);
            paragraph.setSpacingBefore(1f);
            paragraph.setSpacingAfter(1f);
        }
        return paragraph;
    }

    /**
     * 设置自定义文本
     * @param text 文本内容
     * @param size 文本字号
     * @param alignment 对齐方式
     * @param firstLineIndex 首行是否进行缩进
     * @param spacingBefore 段落上空白
     * @param spacingAfter 段落下空白
     * @return
     */
    public void setParagraph(String text, Float size, int alignment, int firstLineIndex, Float spacingBefore, Float spacingAfter) {
        Paragraph paragraph = new Paragraph(text, defaultFont(size));
        if (alignment != 0) {
            paragraph.setAlignment(alignment);
        }
        paragraph.setFirstLineIndent(firstLineIndex);
        paragraph.setSpacingBefore(spacingBefore);
        paragraph.setSpacingAfter(spacingAfter);
        addContent(paragraph);
    }

    /**
     * 添加 PDF 内容
     * 新增工具类方法时,把想生成的内容先调用此方法
     * @param element
     * @return 如果添加了元素,则为true ,否则为false
     */
    public boolean addContent(Element element) {
        try {
            return this.add(element);
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        }
    }


    //------------------------------------表格内容------------------------------------

    /**
     * 表格内容
     * @param content
     * @param alignmentMode
     * @return
     * @throws IOException
     * @throws DocumentException
     */
    public PdfPCell createCell(String content, int alignmentMode) throws IOException, DocumentException {
        PdfPCell cell = new PdfPCell();
        cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        cell.setHorizontalAlignment(alignmentMode);
        cell.setPhrase(new Phrase(content, defaultFont()));
        return cell;
    }

    /**
     * 表格内既有文字又有图片
     * @param content
     * @return
     * @throws IOException
     * @throws DocumentException
     */
    public Phrase createTextInImageCell(String content) throws IOException, DocumentException {
        return new Phrase(content, defaultFont());
    }

    /**
     * 表格内居中对齐
     * @param content
     * @return
     * @throws IOException
     * @throws DocumentException
     */
    public PdfPCell createCenterCell(String content) throws IOException, DocumentException {
        PdfPCell cell = createCell(content, Element.ALIGN_CENTER);
        return cell;
    }

    /**
     * 表格内左对齐
     * @param content
     * @return
     * @throws IOException
     * @throws DocumentException
     */
    public PdfPCell createLeftCell(String content) throws IOException, DocumentException {
        PdfPCell cell = createCell(content, Element.ALIGN_LEFT);
        return cell;
    }

    //------------------------------------字体------------------------------------

    /**
     * 默认中文字体<br>
     * 大小:12<br>
     * 样式:正常<br>
     * 颜色:黑色<br>
     * @return 中文字体 {@link Font}
     */
    public Font defaultFont() {
        return chineseFont(10.5f, Font.NORMAL, BaseColor.BLACK);
    }

    /**
     * 自定义字体的默认中文字体
     * @param size
     * @return
     */
    public Font defaultFont(Float size) {
        return chineseFont(size, Font.NORMAL, BaseColor.BLACK);
    }

    /**
     * 默认中文字体
     * @return 中文字体 {@link BaseFont}
     */
    public BaseFont defaultBaseFont() {
        try {
            return BaseFont.createFont(FONT_NAME_ST_SONG_LIGHT, FONT_ENCODING_UNI_GB_UCS2_H, BaseFont.EMBEDDED);
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 中文字体 {@link Font}
     * @param fontSize 字体大小
     * @param style 字体风格 {@link Font}
     * @param color 字体颜色 {@link BaseColor}
     * @return {@link Font}
     */
    public Font chineseFont(float fontSize, int style, BaseColor color) {
        BaseFont baseFont = null;
        try {
            baseFont = BaseFont.createFont(FONT_NAME_ST_SONG_LIGHT, FONT_ENCODING_UNI_GB_UCS2_H, BaseFont.EMBEDDED);
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return createFont(baseFont, fontSize, style, color);
    }

    /**
     * 自定义中文字体 {@link Font}
     * @param fontPath 字体格式文件路径(如:.ttc、.ttf),支持绝对路径或项目静态资源相对路径
     * @param fontSize 字体大小
     * @param style 字体风格 {@link Font}
     * @param color 字体颜色 {@link BaseColor}
     * @return {@link Font}
     */
    public Font customFont(String fontPath, float fontSize, int style, BaseColor color) {
        BaseFont baseFont = null;
        try {
            baseFont = BaseFont.createFont(fontPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        } catch (DocumentException e) {
            throw new RuntimeException(e);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return createFont(baseFont, fontSize, style, color);
    }


    /**
     * 创建字体 {@link Font}
     * @param baseFont 字体 {@link BaseFont}
     * @param fontSize 字体大小
     * @param style 字体风格 {@link Font}
     * @param color 字体颜色 {@link BaseColor}
     * @return {@link Font}
     */
    public Font createFont(BaseFont baseFont, float fontSize, int style, BaseColor color) {
        return new Font(baseFont, fontSize, style, color);
    }


    /**
     * 字体
     * @return
     * @throws IOException
     * @throws DocumentException
     */
    public BaseFont getBaseFont() throws IOException, DocumentException {
        return BaseFont.createFont(FONT_NAME_ST_SONG_LIGHT, FONT_ENCODING_UNI_GB_UCS2_H, BaseFont.NOT_EMBEDDED);
    }

    //------------------------------------其他------------------------------------

    /**
     * 根据标题列表计算列表列数
     * @param header 标题列表
     * @return 列表列数
     */
    private int calculateColumnNumber(List<String> header) {
        int numColumns = 0;
        for (String s : header) {
            numColumns += calculateColumnNumber(s);
        }
        return numColumns;
    }

    /**
     * 根据标题计算列表列数
     * @param header 标题列表
     * @return 列表列数
     */
    private int calculateColumnNumber(String header) {
        int numColumns = header.length();
        if (!isChinese(header)) {
            numColumns = numColumns / 2 + (numColumns % 2 != 0 ? 1 : 0);
        }
        return numColumns;
    }

    /**
     * 字符串是否是中文
     * @param str 字符串
     * @return 是否是中文
     */
    private boolean isChinese(String str) {
        Pattern p = Pattern.compile("[\u4e00-\u9fa5]");
        Matcher m = p.matcher(str);
        return m.find();
    }

}