package com.ruoyi.common.utils.pdf;

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 javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Objects;

/**
 * @title: PDFUtil
 * @description: PDF工具类
 * @date 2023/4/28 11:22
 */
public class PDFUtil {

    /**
     * 中文编码格式
     */
    public static final String BASE_FONT_CHINESE_ENCODING = "UniGB-UCS2-H";

    /**
     * 宋体
     */
    public static final String FONT_SONG = "STSong-Light";

    /**
     * @MethodName createDocument
     * @Description 获取Document实体
     * @date: 2023/4/28 11:24
     * @return: Document
     */
    public static Document createDocument() {
        return new Document();
    }

    /**
     * @MethodName getOutStream
     * @Description 获取输出流，并且将Document放入流中
     * @date: 2023/4/28 11:25
     * @param: document
     * @return: ByteArrayOutputStream
     */
    public static ByteArrayOutputStream getOutStream(Document document) throws DocumentException {
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
        PdfWriter.getInstance(document, outputStream);
        return outputStream;
    }

    /**
     * @MethodName getBaseFont
     * @Description 获取基础字体设置BaseFont
     * @date: 2023/4/28 14:27
     * @param: name 字体名称
     * @param: encoding 编码格式（中文默认设置为：UniGB-UCS2-H，不支持UTF-8）
     * @param: isEmbedded
     * @return: BaseFont
     */
    public static BaseFont getBaseFont(String name, String encoding, Boolean isEmbedded) throws DocumentException, IOException {
        return BaseFont.createFont(name, encoding, isEmbedded);
    }

    /**
     * @MethodName getFont
     * @Description 获取字体
     * @date: 2023/4/28 14:32
     * @param: baseFont 字体基础设置
     * @param: fontSize 字体大小
     * @param: style 字体样式（参考Font类）
     * @return: Font
     */
    public static Font getFont(BaseFont baseFont, float fontSize, Integer style) {
        return new Font(baseFont, fontSize, style);
    }

    /**
     * @MethodName getChunk
     * @Description 获取标题或者需指定样式的内容
     * @date: 2023/4/28 14:38
     * @param: content 内容
     * @param: font 字体
     * @return: Chunk
     */
    public static Chunk getChunk(String content, Font font) {
        return new Chunk(content, font);
    }

    /**
     * @MethodName getParagraph
     * @Description 获取段落
     * @date: 2023/4/28 14:40
     * @param: alignment 对齐方式（参考Element类）
     * @param: spacingAfter 段落之前间距
     * @param: spacingBefore 段落之后间距
     * @return: Paragraph
     */
    public static Paragraph getParagraph(Integer alignment, Integer spacingAfter, Integer spacingBefore) {
        Paragraph paragraph = new Paragraph();
        if (Objects.nonNull(alignment)) paragraph.setAlignment(alignment);
        if (Objects.nonNull(spacingAfter)) paragraph.setSpacingAfter(spacingAfter);
        if (Objects.nonNull(spacingBefore)) paragraph.setSpacingBefore(spacingBefore);
        return paragraph;
    }

    /**
     * @MethodName getParagraph
     * @Description 获取带有内容的段落
     * @date: 2023/4/28 14:43
     * @param: chunk 内容对象
     * @param: alignment 对齐方式（参考Element类）
     * @param: spacingAfter 段落之前间距
     * @param: spacingBefore 段落之后间距
     * @return: Paragraph
     */
    public static Paragraph getParagraph(Chunk chunk, Integer alignment, Integer spacingAfter, Integer spacingBefore) {
        Paragraph paragraph = new Paragraph(chunk);
        paragraph.setLeading(35);

        if (Objects.nonNull(alignment)) paragraph.setAlignment(alignment);
        if (Objects.nonNull(spacingAfter)) paragraph.setSpacingAfter(spacingAfter);
        if (Objects.nonNull(spacingBefore)) paragraph.setSpacingBefore(spacingBefore);
        return paragraph;
    }

    /**
     * @MethodName getPdfPTable
     * @Description 获取表格
     * @date: 2023/4/28 14:57
     * @param: numColumns 表格列数，无需设置行数，会根据填充的值生成
     * @param: widthPercentage 表格占用页面百分比
     * @param: totalWidth 表格宽度
     * @return: PdfPTable
     */
    public static PdfPTable getPdfPTable(Integer numColumns, float widthPercentage, float totalWidth) {
        PdfPTable table = new PdfPTable(numColumns);
        if (Objects.nonNull(widthPercentage)) table.setWidthPercentage(widthPercentage);
        if (Objects.nonNull(totalWidth)) table.setTotalWidth(totalWidth);
        return table;
    }

    /**
     * @MethodName getPdfCell
     * @Description 获取单元格对象
     * @date: 2023/4/28 16:19
     * @param: phrase 单元内容
     * @param: horizontalAlignment 垂直样式（例如：垂直居中，具体参数参考 Element 类）
     * @param: verticalAlignment 水平样式（例如：水平居中，具体参数参考 Element 类）
     * @param: fixedHeight 固定高度
     * @param: isSetBorder 是否设置框线（此方法设置为单框线）
     * @return: PdfPCell
     */
    public static PdfPCell getPdfCell(Phrase phrase, Integer horizontalAlignment,
                                      Integer verticalAlignment, Integer fixedHeight, Boolean isSetBorder) {
        PdfPCell pdfPCell = new PdfPCell(phrase);
        if (Objects.nonNull(horizontalAlignment)) pdfPCell.setHorizontalAlignment(horizontalAlignment);
        if (Objects.nonNull(verticalAlignment)) pdfPCell.setVerticalAlignment(verticalAlignment);
        if (Objects.nonNull(fixedHeight)) pdfPCell.setFixedHeight(fixedHeight);
        if (isSetBorder) pdfPCell.setBorder(PdfPCell.LEFT | PdfPCell.RIGHT | PdfPCell.BOTTOM | PdfPCell.TOP);
        return pdfPCell;
    }

    /**
     * @MethodName getColSpanPdfCell
     * @Description 获取合并单元格
     * @date: 2023/4/28 16:34
     * @param: phrase 单元内容
     * @param: horizontalAlignment 垂直样式（例如：垂直居中，具体参数参考 Element 类）
     * @param: verticalAlignment 水平样式（例如：水平居中，具体参数参考 Element 类）
     * @param: fixedHeight 固定高度
     * @param: isSetBorder 是否设置框线（此方法设置为单框线）
     * @param: colspan 合并单元格数量
     * @return: PdfPCell
     */
    public static PdfPCell getColSpanPdfCell(Phrase phrase, Integer horizontalAlignment,
                                             Integer verticalAlignment, Integer fixedHeight,
                                             Boolean isSetBorder, Integer colspan,Integer rowsSpan) {
        PdfPCell pdfPCell = new PdfPCell(phrase);
        if (Objects.nonNull(horizontalAlignment)) pdfPCell.setHorizontalAlignment(horizontalAlignment);
        if (Objects.nonNull(verticalAlignment)) pdfPCell.setVerticalAlignment(verticalAlignment);
        if (Objects.nonNull(fixedHeight)) pdfPCell.setFixedHeight(fixedHeight);
        if (isSetBorder) pdfPCell.setBorder(PdfPCell.LEFT | PdfPCell.RIGHT | PdfPCell.BOTTOM | PdfPCell.TOP);
        pdfPCell.setColspan(colspan);
        pdfPCell.setRowspan(rowsSpan);
        return pdfPCell;
    }

    /**
     * @MethodName getPhrase
     * @Description 获取单元内容
     * @date: 2023/4/28 16:23
     * @param: content 单元格内容
     * @param: font 字体
     * @return: Phrase
     */
    public static Phrase getPhrase(String content, Font font) {
        return new Phrase(content, font);
    }

    /**
     * @MethodName addPdfPCell
     * @Description 将内容添加至单元格对象中，并且添加至表格中
     * @date: 2023/4/28 16:27
     * @param: content 内容
     * @param: font 字体样式
     * @param: pdfPCell 单元格
     * @param: pdfPTable 表格
     * @param: fixedHeight 固定高度
     * @return: void
     */
    public static void addPdfPCell(String content, Font font, PdfPCell pdfPCell,PdfPTable pdfPTable,Integer fixedHeight) {
        pdfPCell.setPhrase(new Phrase(content, font));
        pdfPCell.setBackgroundColor(null);
        if (Objects.nonNull(fixedHeight)) pdfPCell.setFixedHeight(fixedHeight);
        pdfPTable.addCell(pdfPCell);

    }

    /**
     * 表头
     * @param content
     * @param font
     * @param pdfPCell
     * @param pdfPTable
     * @param fixedHeight
     */
    public static void addPdfPTitleCell(String content, Font font, PdfPCell pdfPCell,PdfPTable pdfPTable,Integer fixedHeight) {
        pdfPCell.setPhrase(new Phrase(content, font));
        pdfPCell.setBackgroundColor(new BaseColor(239, 248, 252));

        if (Objects.nonNull(fixedHeight)) pdfPCell.setFixedHeight(fixedHeight);

        pdfPTable.addCell(pdfPCell);
    }


    /**
     * @MethodName exportPDF
     * @Description 导出PDF
     * @date: 2023/4/28 16:37
     * @param: document
     * @param: response
     * @param: outputStream
     * @return: void
     */
    public static void exportPDF(Document document, HttpServletResponse response, ByteArrayOutputStream outputStream) throws IOException {
        try {
            if (Objects.isNull(document)) return;
            response.reset();
            document.close();
            response.setCharacterEncoding("UTF-8");
            response.setContentType("application/pdf");
            response.setHeader("Content-disposition", "attachment;filename=table.pdf");
            response.setContentLength(outputStream.size());
            outputStream.writeTo(response.getOutputStream());
            outputStream.flush();
        } finally {
            try {
                outputStream.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
    }



}