package com.qmth.paper.library.common.util.excel;

import com.qmth.paper.library.common.annotation.excelStyle.ExcelDataStyle;
import com.qmth.paper.library.common.annotation.excelStyle.ExcelHeaderStyle;
import com.qmth.paper.library.common.contant.SystemConstant;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.xssf.usermodel.XSSFCellStyle;
import org.apache.poi.xssf.usermodel.XSSFColor;
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;

import java.awt.Color;
import java.io.OutputStream;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Collection;
import java.util.List;
import java.util.Objects;

public class ExcelWriter extends ExcelExport {

    private final XSSFWorkbook workbook;// 工作簿

    private Sheet sheet; // 工作表

    private Row row = null;// 创建一行

    private Cell cell = null;

    private XSSFCellStyle style;

    private XSSFCellStyle style2;

    public ExcelWriter() {
        workbook = new XSSFWorkbook();
    }

    public ExcelWriter(Class<?> dataClass, String sheetName) {
        super(dataClass);
        // 声明一个工作薄
        // workbook = new SXSSFWorkbook(100);//使用该方法会有权限问题
        workbook = new XSSFWorkbook();
        // 生成一个表格
        sheet = workbook.createSheet(sheetName);
        // 设置表格默认列宽度为15个字节
        sheet.setDefaultColumnWidth((short) 15);
    }

    public Sheet createSheet(Class<?> dataClass, String sheetName) {
        setDataClass(dataClass);
        setColumnSettings(getColumnSettings(dataClass));
        Sheet sheet = workbook.createSheet(sheetName);
        // 设置表格默认列宽度为15个字节
        sheet.setDefaultColumnWidth((short) 15);
        return sheet;
    }

    private List<ColumnSetting> createColumnSettings() {
        List<ColumnSetting> columnSettings = this.getColumnSettings();
        // 产生表格标题行
        row = sheet.createRow(0);
        style = workbook.createCellStyle();
        ExcelHeaderStyle excelHeaderStyle = this.getDataClass().getAnnotation(ExcelHeaderStyle.class);
        if (Objects.nonNull(excelHeaderStyle)) {
            // 文字位置
            style.setAlignment(excelHeaderStyle.horizontal());
            style.setVerticalAlignment(excelHeaderStyle.vertical());

            //边框
            int borderRed = excelHeaderStyle.borderColorRed();
            int borderGreen = excelHeaderStyle.borderColorGreen();
            int borderBlue = excelHeaderStyle.borderColorBlue();
            XSSFColor borderColor = new XSSFColor(new Color(borderRed, borderGreen, borderBlue), workbook.getStylesSource().getIndexedColors());
            // 上边框
            if (excelHeaderStyle.borderTop().getCode() > 0) {
                style.setBorderTop(excelHeaderStyle.borderTop());
                style.setTopBorderColor(borderColor);
            }
            // 下边框
            if (excelHeaderStyle.borderBottom().getCode() > 0) {
                style.setBorderBottom(excelHeaderStyle.borderBottom());
                style.setBottomBorderColor(borderColor);
            }
            // 左边框
            if (excelHeaderStyle.borderLeft().getCode() > 0) {
                style.setBorderLeft(excelHeaderStyle.borderLeft());
                style.setLeftBorderColor(borderColor);
            }
            // 右边框
            if (excelHeaderStyle.borderRight().getCode() > 0) {
                style.setBorderRight(excelHeaderStyle.borderRight());
                style.setRightBorderColor(borderColor);
            }

            // 背景
            style.setFillPattern(excelHeaderStyle.fillPartner());
            XSSFColor fillColor = new XSSFColor(new Color(excelHeaderStyle.fillColorRed(), excelHeaderStyle.fillColorGreen(), excelHeaderStyle.fillColorBlue()), workbook.getStylesSource().getIndexedColors());
            style.setFillForegroundColor(fillColor);

            // 字体
            Font font = workbook.createFont();
            font.setFontHeightInPoints(excelHeaderStyle.fontSize());
            font.setFontName(excelHeaderStyle.fontName());
            font.setColor(excelHeaderStyle.fontColor().getIndex());
            style.setFont(font);
        } else {
            style.setFillForegroundColor(new XSSFColor(new Color(227, 239, 217), workbook.getStylesSource().getIndexedColors()));
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
        }
        for (short i = 0; i < columnSettings.size(); i++) {
            cell = row.createCell(i);
            cell.setCellStyle(style);
            XSSFRichTextString text = new XSSFRichTextString(columnSettings.get(i).getHeader());
            cell.setCellValue(text);
            if (columnSettings.get(i).getWidth() > 0) {
                sheet.setColumnWidth(i, columnSettings.get(i).getWidth() * 256);
            }
        }
        return columnSettings;
    }

    /**
     * 写入excel
     *
     * @param dataset 数据集合
     * @param out     输出流
     * @throws SecurityException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     */
    public void write(Collection<?> dataset, OutputStream out) throws Exception {
        List<ColumnSetting> columnSettings = this.createColumnSettings();
        int index = 0;
        if (Objects.nonNull(dataset) && dataset.size() > 0) {
            for (Object obj : dataset) {
                index++;
                row = sheet.createRow(index);// 创建行
                // 利用反射，根据javabean属性的先后顺序，动态调用getXxx()方法得到属性值
                for (short i = 0; i < columnSettings.size(); i++) {
                    cell = row.createCell(i);// 创建列
                    Field field = columnSettings.get(i).getField();

                    cell.setCellStyle(this.getCellStyle(workbook.createCellStyle(), field));
                    String methodName = columnSettings.get(i).getGetMethodName();
                    Method method = this.getDataClass().getMethod(methodName, new Class[]{});
                    Object value = method.invoke(obj, new Object[]{});
                    cell.setCellValue(value == null ? "" : value.toString());
                }
            }
        }
        workbook.write(out);
    }

    /**
     * 写入excel
     *
     * @param dataset 数据集合
     * @param sheet
     * @throws SecurityException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     * @throws IllegalArgumentException
     * @throws IllegalAccessException
     */
    public void write(Collection<?> dataset, Sheet sheet) throws Exception {
        List<ColumnSetting> columnSettings = this.createColumnSettings(sheet);
        int index = 0;
        if (Objects.nonNull(dataset) && dataset.size() > 0) {
            for (Object obj : dataset) {
                index++;
                row = sheet.createRow(index);// 创建行
                // 利用反射，根据javabean属性的先后顺序，动态调用getXxx()方法得到属性值
                for (short i = 0; i < columnSettings.size(); i++) {
                    cell = row.createCell(i);// 创建列
                    cell.setCellStyle(style2);
                    String methodName = columnSettings.get(i).getGetMethodName();
                    Method method = this.getDataClass().getMethod(methodName, new Class[]{});
                    Object value = method.invoke(obj, new Object[]{});
                    cell.setCellValue(value == null ? "" : value.toString());
                }
            }
        }
//        workbook.write(out);
    }

    private List<ColumnSetting> createColumnSettings(Sheet sheet) {
        List<ColumnSetting> columnSettings = this.getColumnSettings();
        // 产生表格标题行
        row = sheet.createRow(0);
        for (short i = 0; i < columnSettings.size(); i++) {
            cell = row.createCell(i);
            style = workbook.createCellStyle();
            style.setFillForegroundColor(new XSSFColor(new Color(227, 239, 217), workbook.getStylesSource().getIndexedColors()));
            style.setFillPattern(FillPatternType.SOLID_FOREGROUND);
            cell.setCellStyle(style);
            XSSFRichTextString text = new XSSFRichTextString(columnSettings.get(i).getHeader());
            cell.setCellValue(text);
            if (columnSettings.get(i).getWidth() > 0) {
                sheet.setColumnWidth(i, columnSettings.get(i).getWidth() * 256);
            }
        }
        return columnSettings;
    }

    public XSSFWorkbook getWorkbook() {
        return workbook;
    }

    private XSSFCellStyle getCellStyle(XSSFCellStyle style, Field field) {
        ExcelDataStyle excelDataStyle = field.getAnnotation(ExcelDataStyle.class);
        if (Objects.isNull(excelDataStyle)) {
            return style;
        } else {
            // 文字位置
            style.setAlignment(excelDataStyle.horizontal());
            style.setVerticalAlignment(excelDataStyle.vertical());

            //边框
            int borderRed = excelDataStyle.borderColorRed();
            int borderGreen = excelDataStyle.borderColorGreen();
            int borderBlue = excelDataStyle.borderColorBlue();
            XSSFColor borderColor = new XSSFColor(new Color(borderRed, borderGreen, borderBlue), workbook.getStylesSource().getIndexedColors());
            // 上边框
            if (excelDataStyle.borderTop().getCode() > 0) {
                style.setBorderTop(excelDataStyle.borderTop());
                style.setTopBorderColor(borderColor);
            }
            // 下边框
            if (excelDataStyle.borderBottom().getCode() > 0) {
                style.setBorderBottom(excelDataStyle.borderBottom());
                style.setBottomBorderColor(borderColor);
            }
            // 左边框
            if (excelDataStyle.borderLeft().getCode() > 0) {
                style.setBorderLeft(excelDataStyle.borderLeft());
                style.setLeftBorderColor(borderColor);
            }
            // 右边框
            if (excelDataStyle.borderRight().getCode() > 0) {
                style.setBorderRight(excelDataStyle.borderRight());
                style.setRightBorderColor(borderColor);
            }

            // 背景
            style.setFillPattern(excelDataStyle.fillPartner());
            XSSFColor fillColor = new XSSFColor(new Color(excelDataStyle.fillColorRed(), excelDataStyle.fillColorGreen(), excelDataStyle.fillColorBlue()), workbook.getStylesSource().getIndexedColors());
            style.setFillForegroundColor(fillColor);

            // 字体
            Font font = workbook.createFont();
            font.setFontHeightInPoints(excelDataStyle.fontSize());
            font.setFontName(excelDataStyle.fontName());
            font.setColor(excelDataStyle.fontColor().getIndex());
            style.setFont(font);

            // 锁定
            if (excelDataStyle.lock()) {
                style.setLocked(true);
                sheet.protectSheet(SystemConstant.EXCEL_PROTECT_KEY);
            } else {
                style.setLocked(false);
            }
            return style;
        }
    }
}
