package com.yeejoin.precontrol.common.fileparser.product.html;


import com.yeejoin.precontrol.common.fileparser.utils.FileHelper;
import com.yeejoin.precontrol.common.fileparser.utils.TikaUtils;
import com.yeejoin.precontrol.common.service.FileService;
import com.yeejoin.precontrol.common.service.impl.FileServiceImpl;
import com.yeejoin.precontrol.common.utils.ByteToInputStream;
import com.yeejoin.precontrol.common.utils.SpringUtils;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.fileupload.FileItem;
import org.apache.commons.fileupload.disk.DiskFileItem;
import org.apache.commons.io.IOUtils;
import org.apache.http.entity.ContentType;
import org.apache.poi.hwpf.HWPFDocument;
import org.apache.poi.hwpf.converter.PicturesManager;
import org.apache.poi.hwpf.converter.WordToHtmlConverter;
import org.apache.poi.hwpf.usermodel.Picture;
import org.apache.poi.hwpf.usermodel.PictureType;
import org.apache.poi.xwpf.converter.core.FileImageExtractor;
import org.apache.poi.xwpf.converter.core.IURIResolver;
import org.apache.poi.xwpf.converter.core.IXWPFConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLConverter;
import org.apache.poi.xwpf.converter.xhtml.XHTMLOptions;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mock.web.MockMultipartFile;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.commons.CommonsMultipartFile;
import org.w3c.dom.Document;

import javax.imageio.ImageIO;
import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.nio.file.Files;
import java.util.List;

@Slf4j
public class WordHtml implements AbstractHtml {


    @Autowired
    FileService fileService;

    //坑 因为无法注入成功 所以配置死的
    String fileServerUrl = "http://172.16.10.175:8888/";

    @Override
    public void createHtml(String inputFile, String outputFile) throws Exception {
        log.info("将word转换为html文件开始,输出文件 [" + outputFile + ".html]......");
        long startTime = System.currentTimeMillis();
        InputStream is = null;
        try {
            File file = new File(outputFile);
            if (!file.exists()) {
                file.mkdirs();
            }

            File input = new File(inputFile);
            if (!file.exists()) {
                log.error("file not found:" + inputFile);
            }

            is = new FileInputStream(input);
            if (FileHelper.isWord2003(input)) {
                convertDoc2Html(is, outputFile);
            } else if (FileHelper.isWord2007(input)) {
                convertDocx2Html(is, outputFile);
            } else {
                TikaUtils.parseToHtml(inputFile, outputFile);
            }
        } finally {
            try {
                if (null != is) {
                    is.close();
                }
            } catch (Exception e) {

            }
        }
        log.info("将word转换为html文件......ok");
        log.info("Generate " + outputFile + ".html with " + (System.currentTimeMillis() - startTime)
                + " ms.");
    }

    /**
     * 将doc文档转换为html文件
     *
     * @param outPutFile 输出html文件的全路径
     * @throws TransformerException
     * @throws IOException
     * @throws ParserConfigurationException
     * @see
     * @since 1.7
     */
    private void convertDoc2Html(InputStream is, String outPutFile)
            throws TransformerException, IOException, ParserConfigurationException {
        StreamResult streamResult = null;
        ByteArrayOutputStream out = null;
        try {
            String[] outPutFiles = outPutFile.split("\\\\");
            outPutFiles = outPutFiles[outPutFiles.length - 1].split("/");
            final String root = outPutFiles[outPutFiles.length - 1];
            // 将文件转换为poi数据结构
            HWPFDocument wordDocument = new HWPFDocument(is);
            Document document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument();
            // 获取word转换为html的句柄
            WordToHtmlConverter wordToHtmlConverter = new WordToHtmlConverter(document);
            // 设置html文件中图片引入路径

            //noinspection AliMissingOverrideAnnotation
            wordToHtmlConverter.setPicturesManager(new PicturesManager() {
                @SneakyThrows
                @Override
                public String savePicture(byte[] content, PictureType pictureType, String suggestedName,
                                          float widthInches, float heightInches) {
                    //改为fastDfs上传地址
                    byte[] image = content;
                    if (widthInches > 2) {
                        image = imageStringByte(450, content);
                    }
                    FileServiceImpl fileService = SpringUtils.getBean(FileServiceImpl.class);
                    InputStream inputStream = ByteToInputStream.byte2Input(image);


                    MultipartFile file = new MockMultipartFile("tempFile", suggestedName,
                            ContentType.APPLICATION_OCTET_STREAM.toString(), inputStream);
                    String uploadfile = fileService.uploadfile(file);
                    //return root + "/" + suggestedName;
                    return fileServerUrl + uploadfile;
                }
            });
            wordToHtmlConverter.processDocument(wordDocument);
            // #start save pictures
            List<Picture> pics = wordDocument.getPicturesTable().getAllPictures();
            if (pics != null) {
                for (int i = 0; i < pics.size(); i++) {
                    Picture pic = (Picture) pics.get(i);
                    try {
                        // 指定doc文档中转换后图片保存的路径
                        pic.writeImageContent(
                                new FileOutputStream(outPutFile + "/" + pic.suggestFullFileName()));
                    } catch (FileNotFoundException e) {
                        e.printStackTrace();
                    }
                }
            }
            // #end save pictures
            out = new ByteArrayOutputStream();
            streamResult = new StreamResult(out);
            TransformerFactory tf = TransformerFactory.newInstance();
            tf.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
            // 创建执行从 Source 到 Result 的复制的新 Transformer。
            Transformer serializer = tf.newTransformer();
            serializer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); // 文件编码方式
            serializer.setOutputProperty(OutputKeys.INDENT, "yes"); // indent 指定了当输出结果树时，Transformer
            // 是否可以添加额外的空白；其值必须为 yes 或 no
            serializer.setOutputProperty(OutputKeys.METHOD, "html"); // 指定输出文件的后缀名
            Document htmlDocument = wordToHtmlConverter.getDocument();
            DOMSource domSource = new DOMSource(htmlDocument);
            serializer.transform(domSource, streamResult);
            String content = new String(out.toByteArray());
            FileHelper.writeFile(content, outPutFile + ".html");
            // FileHelper.parseCharset(outPutFile + ".html");
            // System.out.println(new String(out.toByteArray()));
        } finally {
            if (null != out) {
                out.close();
            }
        }
    }

    /**
     * 将docx文件转换为html @param is @param fileOutName 输出文件的具体路径 @throws IOException @see @since
     * 1.7 @exception
     */
    private void convertDocx2Html(InputStream is, String fileOutName) throws IOException {
        OutputStream out = null;
        XWPFDocument document = null;
        try {
            // final String root = fileOutName.substring(fileOutName.lastIndexOf("/") + 1);

            String[] outPutFiles = fileOutName.split("\\\\");
            outPutFiles = outPutFiles[outPutFiles.length - 1].split("/");
            final String root = outPutFiles[outPutFiles.length - 1];

            long startTime = System.currentTimeMillis();
            // 获取解析处理类
            document = new XWPFDocument(is);

            XHTMLOptions options = XHTMLOptions.create();// .indent(4);
            // Extract image
            File imageFolder = new File(fileOutName);
            if (!imageFolder.exists()) {
                imageFolder.mkdirs();
            }
            // 设置图片保存路径
            options.setExtractor(new FileImageExtractor(imageFolder));
            // URI resolver
            options.URIResolver(new IURIResolver() {
                @Override
                public String resolve(String uri) {
                    return root + File.separatorChar + uri;
                }
            });
            out = new FileOutputStream(new File(fileOutName + ".html"));
            IXWPFConverter<XHTMLOptions> xhtmlCoverter = XHTMLConverter.getInstance();
            xhtmlCoverter.convert(document, out, options);
            // FileHelper.parseCharset(fileOutName + ".html");
            log.info(
                    "Generate " + fileOutName + " with " + (System.currentTimeMillis() - startTime) + " ms.");
        } finally {
            try {
                if (null != out) {
                    out.close();
                }
                if (null != document) {
                    document.close();
                }
            } catch (Exception e) {

            }
        }
    }


    /**
     * byte 转换为 MultipartFile
     *
     * @param bytes
     * @return
     */
    public static MultipartFile encodeToMultipartFile(byte[] bytes) {
        MultipartFile multipartFile = null;
        InputStream input = null;
        OutputStream outputStream = null;
        File tempFile = null;
        try {
            // 把 byte 转换为 File 文件
            // 第一个参数 fieldName 就是文件上传的 name, 这里我写的是 uploadFile
            FileItem fileItem = new DiskFileItem("fileName", Files.probeContentType(tempFile.toPath()), false,
                    tempFile.getName(), (int) tempFile.length(), tempFile.getParentFile());
            input = new FileInputStream(tempFile);
            outputStream = fileItem.getOutputStream();
            IOUtils.copy(input, outputStream);
            multipartFile = new CommonsMultipartFile(fileItem);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                input.close();
                outputStream.close();
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        // 删除这个 File
        if (tempFile.exists()) {
            tempFile.delete();
        }

        return multipartFile;
    }


    /**
     * 操作流图片大小
     *
     * @param content
     * @param width
     * @param height
     * @return
     */
    public static byte[] resizeImage(byte[] content, int width, int height) {
        byte[] finalImage = null;
        try {
            ByteArrayInputStream in = new ByteArrayInputStream(content);
            BufferedImage img = ImageIO.read(in);
            int w = img.getWidth();
            int h = img.getHeight();
            BufferedImage dimg = new BufferedImage(width, height, img.getType());
            Graphics2D g = dimg.createGraphics();
            g.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BILINEAR);
            g.drawImage(img, 0, 0, width, height, 0, 0, w, h, null);
            g.dispose();

            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            ImageIO.write(dimg, "png", byteArrayOutputStream);
            finalImage = byteArrayOutputStream.toByteArray();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return finalImage;
    }


    /**
     * 图片缩放
     */
    public static byte[] imageStringByte(int width, byte[] b) {
        InputStream buffin = new ByteArrayInputStream(b);
        BufferedImage src = null;
        try {
            src = ImageIO.read(buffin);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } // 读入文件
        int widthYuan = src.getWidth(); // 得到源图宽
        int heightYuan = src.getHeight(); // 得到源图长
        heightYuan = heightYuan / (widthYuan / width);
        widthYuan = width;
        Image image = src.getScaledInstance(widthYuan, heightYuan, Image.SCALE_DEFAULT);
        BufferedImage tag = new BufferedImage(widthYuan, heightYuan, BufferedImage.TYPE_INT_RGB);
        Graphics g = tag.getGraphics();
        boolean drawImage = g.drawImage(image, 0, 0, null); // 绘制缩小后的图
        g.dispose();
        byte[] bytes = imageToBytes(tag);
        return bytes;// 输出到文件流
    }

    /**
     * BufferedImage转byte[]
     *
     * @param bImage BufferedImage对象
     * @return byte[]
     * @auth zhy
     */
    private static byte[] imageToBytes(BufferedImage bImage) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(bImage, "png", out);
        } catch (IOException e) {
            //log.error(e.getMessage());
        }
        return out.toByteArray();
    }


}

