package com.yiboshi.science.utils;

import com.itextpdf.html2pdf.ConverterProperties;
import com.itextpdf.html2pdf.HtmlConverter;
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.font.FontProvider;
import com.itextpdf.text.pdf.BaseFont;
import com.lowagie.text.DocumentException;
import freemarker.cache.ClassTemplateLoader;
import freemarker.template.Configuration;
import freemarker.template.TemplateException;
import freemarker.template.TemplateExceptionHandler;
import org.apache.velocity.Template;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.context.Context;
import org.apache.velocity.runtime.RuntimeConstants;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import org.xhtmlrenderer.pdf.ITextRenderer;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.OutputStream;
import java.io.StringWriter;
import java.nio.charset.StandardCharsets;
import java.util.Map;

import static java.lang.System.in;

/**
 * PDF工具
 *
 * @author ppp
 * @date 2022/8/5
 */
public class PdfUtil {

    static {
        // Velocity初始化
        Velocity.setProperty(RuntimeConstants.OUTPUT_ENCODING, StandardCharsets.UTF_8);
        Velocity.setProperty(RuntimeConstants.INPUT_ENCODING, StandardCharsets.UTF_8);
        Velocity.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
        Velocity.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
        Velocity.init();
    }


    /**
     * 据模板生成pfd格式文件
     *
     * @param context      上下文对象
     * @param template     pdf模板
     * @param outputStream 生成ofd文件输出流
     */
    public static void pdfFile(Context context, String template, OutputStream outputStream) {
        try (PdfWriter pdfWriter = new PdfWriter(outputStream)) {
            PdfDocument pdfDocument = new PdfDocument(pdfWriter);
            pdfDocument.setDefaultPageSize(PageSize.A4);
            ConverterProperties properties = new ConverterProperties();
            FontProvider fontProvider = new FontProvider();

            // 字体设置,解决中文不显示问题
            PdfFont sysFont = PdfFontFactory.createFont("STSongStd-Light", "UniGB-UCS2-H");
            fontProvider.addFont(sysFont.getFontProgram(), "UniGB-UCS2-H");
            properties.setFontProvider(fontProvider);

            Template pfdTemplate = Velocity.getTemplate(template, "UTF-8");
            StringWriter writer = new StringWriter();
            pfdTemplate.merge(context, writer);

            HtmlConverter.convertToPdf(writer.toString(), pdfDocument, properties);

            pdfDocument.close();
        } catch (Exception e) {
            throw new RuntimeException("PFD文件生成失败", e);
        }
    }

    public static byte[] createPDF(HttpServletResponse response, String temp, Object dataModel) throws IOException, TemplateException, DocumentException {
        Map<String, Object> dataMap = HtmlBuilder.obj2Map(dataModel);
        // 配置FreeMarker
        Configuration cfg = new Configuration(Configuration.DEFAULT_INCOMPATIBLE_IMPROVEMENTS);
        cfg.setDefaultEncoding("utf-8");
        cfg.setClassLoaderForTemplateLoading(PdfUtil.class.getClassLoader(), "template");
        cfg.setTemplateLoader(new ClassTemplateLoader(PdfUtil.class.getClassLoader(), "/template"));
        cfg.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        // 获取模板
        freemarker.template.Template template = cfg.getTemplate(temp, "utf-8");
        // 处理模板,生成HTML内容
        StringWriter tmpText = new StringWriter();
        template.process(dataMap, tmpText);
        String htmlContent = tmpText.toString();
        // 创建PDF渲染器
        ITextRenderer renderer = new ITextRenderer();
        // Java代码示例
//        renderer.getSharedContext().setDPI(1); // 提高DPI减少锯齿
        // 设置中文字体
        String simPath = ResourceFileUtil.getAbsolutePath("/fonts/simsun.ttc");
        String msyhPath = ResourceFileUtil.getAbsolutePath("/fonts/msyh.ttc");
        renderer.getFontResolver().addFont(simPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        renderer.getFontResolver().addFont(msyhPath, BaseFont.IDENTITY_H, BaseFont.EMBEDDED);
        // 渲染HTML内容
        renderer.setDocumentFromString(htmlContent);
        renderer.layout();
        // 创建一个ByteArrayOutputStream来保存生成的PDF
        response.setContentType("application/octet-stream;charset=UTF-8");
        OutputStream outputStream = response.getOutputStream();
        // 输出PDF到字节数组
        renderer.createPDF(outputStream);
        //创建存放文件内容的数组
        byte[] buff = new byte[1024];
        //所读取的内容使用n来接收
        int n;
        //当没有读取完时,继续读取,循环
        while ((n = in.read(buff)) != -1) {
            //将字节数组的数据全部写入到输出流中
            outputStream.write(buff, 0, n);
        }
        //强制将缓存区的数据进行输出
        outputStream.flush();
        //关流
        outputStream.close();
        in.close();
        // 关闭输出流
        return buff;
    }

}