package com.bonus.common.core.utils.poi;

import com.itextpdf.text.DocumentException;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xwpf.usermodel.XWPFDocument;

import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
import org.jfree.chart.ChartUtils;
import org.jfree.chart.JFreeChart;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.math.BigInteger;

public class WordUtil implements DocumentUtil  {

    private final XWPFDocument document;

    /**
    * 创建一个Word文档，并添加文字、图片、表格等元素
     */
    public WordUtil() {
        this.document = new XWPFDocument();
    }

    /**
     * 获取文档对象，以便对文档做其他自定义的操作
     */
    public XWPFDocument getDocument() {
        return document;
    }

    /**
     * 添加一个文字段落，设置字体和大小
     *
     * @param text     文本内容
     * @param fontSize 字体大小
     * @param fontFamily  字体，如果指定字体不在当前系统，则使用默认字体
     * @return XWPFParagraph 段落对象，可以用于更改段落其他属性
     */
    public XWPFParagraph addParagraph(String text, int fontSize, String fontFamily) {
        XWPFParagraph paragraph = document.createParagraph();
        XWPFRun run = paragraph.createRun();
        run.setText(text);
        run.setFontSize(fontSize);
        run.setFontFamily(fontFamily);
        return paragraph;
    }

    /**
     * 创建一个表格，并插入到文档中
     *
     * @param rows 行数
     * @param cols 列数
     * @param content  rows*cols的数组
     * @param columnWidths 每列的宽度，（单位是 twips，1 twip = 1/20 point）
     */
    public XWPFTable addTable(int rows, int cols, String[][] content, int[] columnWidths) {
        XWPFTable table = document.createTable(rows, cols);

        for (int i = 0; i < rows; i++) {
            XWPFTableRow row = table.getRow(i);
            for (int j = 0; j < cols; j++) {
                XWPFTableCell cell = row.getCell(j);
                if (content != null && content.length > i && content[i].length > j) {
                    cell.setText(content[i][j]);
                } else {
                    cell.setText("Row " + (i + 1) + ", Column " + (j + 1));
                }
                // 设置每个单元格的宽度
                cell.getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(columnWidths[j]));
            }
        }
        return table;
    }

    /**
     * 创建图片，并插入到文档中
     *
     * @param imgFilePath 图片本地路径
     * @param width 图片宽，单位像素
     * @param height 图片高，单位像素
     */
    public void insertImage(String imgFilePath, int width, int height) throws RuntimeException {
        try (InputStream is = new FileInputStream(imgFilePath)) {
            XWPFParagraph paragraph = document.createParagraph();
            XWPFRun run = paragraph.createRun();
            run.addPicture(is, XWPFDocument.PICTURE_TYPE_PNG, imgFilePath, Units.toEMU(width), Units.toEMU(height));
        } catch (Exception e) {
            throw new RuntimeException("insertImage exception", e);
        }
    }

    /**
     * 创建柱状图，并插入到文档中
     *
     * @param title 图表标题
     * @param categoryAxisLabel 目录轴的标签
     * @param valueAxisLabel  数据轴的标签
     * @param  rowKeys 目录轴每行的key
     * @param  columnKeys 数据轴每列的key
     * @param data  数据
     * @param width 柱状图的宽,传入非正数则使用默认值400,单位为像素
     * @param height 柱状图的高,传入非正数则使用默认值400,单位为像素
     */
    public void addBarChart(String title, String categoryAxisLabel, String valueAxisLabel,
                                      String[] rowKeys, String[] columnKeys, double[][] data,int width,int height) throws IOException, DocumentException, InvalidFormatException {

        width = (width > 0) ? width : 400;
        height = (height > 0) ? height : 400;

        JFreeChart barChart = createBarChart(title, categoryAxisLabel, valueAxisLabel, rowKeys, columnKeys, data);
        ByteArrayOutputStream chartOut = new ByteArrayOutputStream();
        ChartUtils.writeChartAsPNG(chartOut, barChart, width, height);
        // 将图表字节数组转为输入流并插入到文档中
        ByteArrayInputStream chartIn = new ByteArrayInputStream(chartOut.toByteArray());

        // Add chart to document
        XWPFParagraph paragraph = document.createParagraph();
        XWPFRun run = paragraph.createRun();
        run.addPicture(chartIn, XWPFDocument.PICTURE_TYPE_PNG, "bar_chart.png", Units.toEMU(width), Units.toEMU(height));
    }

    /**
     * 创建饼状图，并插入到文档中
     *
     * @param title 图表标题
     * @param categories 目录轴的标签
     * @param values  数据轴的标签
     */
    public void addPieChart( String title, String[] categories, double[] values,int width,int height) throws IOException, DocumentException, InvalidFormatException {
        JFreeChart pieChart = createPieChart(title, categories, values);
        width = (width > 0) ? width : 400;
        height = (height > 0) ? height : 400;
        //将图表保存到字节数组输出流中
        ByteArrayOutputStream chartOut = new ByteArrayOutputStream();
        ChartUtils.writeChartAsPNG(chartOut, pieChart, width, height);
        ByteArrayInputStream chartIn = new ByteArrayInputStream(chartOut.toByteArray());

        //将图表字节数组转为输入流并插入到文档中
        XWPFParagraph paragraph = document.createParagraph();
        XWPFRun run = paragraph.createRun();
        run.addPicture(chartIn, XWPFDocument.PICTURE_TYPE_PNG, "pie_chart.png", Units.toEMU(400), Units.toEMU(400));
    }

    /**
     * 保存文档
     * @param filePath 文档本地路径
     */
    public void saveDocumentToLocal(String filePath) throws IOException {
        FileOutputStream out = new FileOutputStream(filePath);
        document.write(out);
    }

    /**
     * 保存文档到HttpServletResponse对象中
     * @param response 返回数据
     */
    public void saveDocumentToResponse(HttpServletResponse response) throws IOException{
        response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        response.setCharacterEncoding("utf-8");
        OutputStream out = response.getOutputStream();
        document.write(out);
    }
    /**
     * 关闭文档
     * 完成保存结束后，一定调用此方法，否则会产生内容泄露的风险
     */
    public void closeDocument() throws IOException {
     document.close();
    }

}
