package com.chinaweal.aiccs.common.util;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.TimeInterval;
import cn.hutool.core.io.IoUtil;
import com.chinaweal.aiccs.common.util.filestorage.FileStorageService;
import com.chinaweal.youfool.framework.springboot.util.SpringUtil;
import lombok.extern.slf4j.Slf4j;
import org.docx4j.Docx4J;
import org.docx4j.convert.out.FOSettings;
import org.docx4j.fonts.IdentityPlusMapper;
import org.docx4j.fonts.Mapper;
import org.docx4j.fonts.PhysicalFonts;
import org.docx4j.openpackaging.packages.WordprocessingMLPackage;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;

/**
 * @author Lee
 * @since 2021/6/3 14:46
 */
@Slf4j
public class PdfUtil {

    public final static Mapper FONT_MAPPER = new IdentityPlusMapper(){{
        put("隶书", PhysicalFonts.get("LiSu"));
        put("宋体", PhysicalFonts.get("SimSun"));
        put("微软雅黑", PhysicalFonts.get("Microsoft Yahei"));
        put("黑体", PhysicalFonts.get("SimHei"));
        put("楷体", PhysicalFonts.get("KaiTi"));
        put("新宋体", PhysicalFonts.get("NSimSun"));
        put("华文行楷", PhysicalFonts.get("STXingkai"));
        put("华文仿宋", PhysicalFonts.get("STFangsong"));
        put("宋体扩展", PhysicalFonts.get("simsun-extB"));
        put("仿宋", PhysicalFonts.get("FangSong"));
        put("仿宋_GB2312", PhysicalFonts.get("FangSong_GB2312"));
        put("幼圆", PhysicalFonts.get("YouYuan"));
        put("华文宋体", PhysicalFonts.get("STSong"));
        put("华文中宋", PhysicalFonts.get("STZhongsong"));
        put("等线", PhysicalFonts.get("SimSun"));
        put("等线 Light", PhysicalFonts.get("SimSun"));
    }};

    public static Mapper getFontMapper(){
        return FONT_MAPPER;
    }

    /**
     * word（docx）转pdf
     * @param wordPath  docx文件路径
     * @return  生成的pdf路径
     */
    public static String convertDocx2Pdf(String wordPath, String pdfPath) {

        try(InputStream is = Files.newInputStream(new File(wordPath).toPath());
            OutputStream os = Files.newOutputStream(Paths.get(pdfPath))) {

            WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(is);
            mlPackage.setFontMapper(getFontMapper());
            //docx4j  docx转pdf
            FOSettings foSettings = Docx4J.createFOSettings();

            foSettings.setWmlPackage(mlPackage);
            Docx4J.toPDF(mlPackage, os);

            //添加水印
            return pdfPath;
        } catch (Exception e) {
            log.error("word转pdf失败.", e);
            throw new RuntimeException("word转pdf失败.");
        }
    }


    /**
     * word（docx）转pdf
     * @return  生成的pdf路径
     */
    public static String convertDocx2Pdf(ByteArrayOutputStream wordOs, String pdfPath) {
        TimeInterval timer = DateUtil.timer();
        ByteArrayInputStream wordIs = null;
        ByteArrayOutputStream os = null;
        try{
            os = new ByteArrayOutputStream();
            wordIs = new ByteArrayInputStream(wordOs.toByteArray());
            WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(wordIs);
            mlPackage.setFontMapper(getFontMapper());
            //docx4j docx转pdf
            FOSettings foSettings = Docx4J.createFOSettings();
            foSettings.setWmlPackage(mlPackage);
            Docx4J.toPDF(mlPackage, os);
            log.debug("word转换pdf完成，耗时（毫秒）： {}", timer.interval());

            FileStorageService fileStorageService = SpringUtil.getBean(FileStorageService.class);
            boolean upload = fileStorageService.writeFromStream(pdfPath, new ByteArrayInputStream(os.toByteArray()));
            if(!upload){
                log.error("上传失败.",pdfPath);
                throw new RuntimeException("上传失败.");
            }

            return pdfPath;
        } catch (Exception e) {
            log.error("word转pdf失败.", e);
            throw new RuntimeException("word转pdf失败.");
        }finally {
            if(wordIs != null) {
                IoUtil.close(wordIs);
            }
            if(wordOs != null) {
                IoUtil.close(wordOs);
            }
            if(os != null) {
                IoUtil.close(os);
            }
        }
    }

    /**
     * word（docx）转pdf 字节流
     * @return  生成的pdf字节流
     */
    public static String convertDocx2PdfStream(ByteArrayOutputStream wordOs, String pdfPath, HttpServletResponse response) {
        TimeInterval timer = DateUtil.timer();
        ByteArrayInputStream wordIs = null;
        ServletOutputStream os = null;
        try{
            os = response.getOutputStream();
            wordIs = new ByteArrayInputStream(wordOs.toByteArray());
            WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(wordIs);
            mlPackage.setFontMapper(getFontMapper());

            //docx4j docx转pdf
            FOSettings foSettings = Docx4J.createFOSettings();
            foSettings.setWmlPackage(mlPackage);
            Docx4J.toPDF(mlPackage, os);
            log.debug("word转换pdf完成，耗时（毫秒）： {}", timer.interval());

            return pdfPath;
        } catch (Exception e) {
            log.error("word转pdf失败.", e);
            throw new RuntimeException("word转pdf失败.");
        }finally {
            if(wordIs != null) {
                IoUtil.close(wordIs);
            }
            if(wordOs != null) {
                IoUtil.close(wordOs);
            }
            if(os != null) {
                IoUtil.close(os);
            }
        }
    }
    /**
     * word（docx）转pdf 字节流
     * @return  生成的pdf字节流
     */
    public static ServletOutputStream convertDocx2PdfStream(ByteArrayOutputStream wordOs, ServletOutputStream pdfOs) {
        TimeInterval timer = DateUtil.timer();
        ByteArrayInputStream wordIs = null;
        try{
            wordIs = new ByteArrayInputStream(wordOs.toByteArray());
            WordprocessingMLPackage mlPackage = WordprocessingMLPackage.load(wordIs);
            mlPackage.setFontMapper(getFontMapper());

            //docx4j docx转pdf
            FOSettings foSettings = Docx4J.createFOSettings();
            foSettings.setWmlPackage(mlPackage);
            Docx4J.toPDF(mlPackage, pdfOs);
            log.debug("word转换pdf完成，耗时（毫秒）： {}", timer.interval());

            return pdfOs;
        } catch (Exception e) {
            log.error("word转pdf失败.", e);
            throw new RuntimeException("word转pdf失败.");
        }finally {
            if(wordIs != null) {
                IoUtil.close(wordIs);
            }
            if(wordOs != null) {
                IoUtil.close(wordOs);
            }
            if(pdfOs != null) {
                IoUtil.close(pdfOs);
            }
        }
    }
}
