package com.bocloud.ims.service.utils;

import com.alibaba.fastjson.JSONObject;
import com.bocloud.common.utils.DateTools;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddressList;
import org.apache.poi.ss.util.WorkbookUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;

/**
 * 利用apache.poi导出EXCEL
 *
 * @author sxp
 * @since Nov 9, 2017
 */
public class ExcelExporter {
    private static Logger logger = LoggerFactory.getLogger(ExcelExporter.class);

    /**
     * 将数据以EXCEL的形式输出到指定IO设备上
     * <p>
     * 在原有export方法的基础上增加入参：firstFewRows、dataColumns，去掉入参flag、pos。<br>
     * 增加对数据集合中各个字段数据类型的判断。 <br>
     * </p>
     *
     * @param title        表格标题名(即SheetName)
     * @param firstFewRows 在显示数据集合之前提前显示的几行数据
     * @param headers      表格属性列名数组
     * @param dataColumns  数据集中的列名，顺序和headers属性列一一对应
     * @param datas        需要显示的数据集合,集合中一定要放置符合javabean风格的类的对象。
     * @param out          与输出设备关联的流对象，可以将EXCEL文档导出到本地文件或者网络中
     * @param dateFormat   如果有时间数据，设定输出格式。默认为"yyyy-MM-dd"
     * @author sxp
     * @since Nov 30, 2016
     * @since 2017-01-03 modify by sxp 在Excel中工作表的名称最大长度为31，并且不能含有9种特殊字符
     * @since 2017-11-17 modify by sxp
     * 修正[只调用setFillPattern的情况下，使用微软Excel打开后背景色为黑色]的bug
     */
    public static void export(String title, List<List<Object>> firstFewRows, String[] headers, String[] dataColumns,
                              List<Map<String, Object>> datas, OutputStream out, String dateFormat) {
        if (null == headers || headers.length <= 0 || null == out) {
            logger.warn("no headers or OutputStream is null");
            return;
        }
        if (null == datas) {
            logger.info("no datas");
            datas = new ArrayList<>();
        }
        if (dateFormat.isEmpty()) {
            dateFormat = "yyyy-MM-dd";
        }

        HSSFWorkbook workbook = new HSSFWorkbook();

        try {
            int sheetNum = 1;
            int currentRowCount = 1;
            // 每个工作薄显示50000条数据(MAX:65536)
            int perPageNum = 50000;

            String safeTitle = WorkbookUtil.createSafeSheetName(title + "_" + sheetNum);
            HSSFSheet sheet = workbook.createSheet(safeTitle);
            sheet.setDefaultColumnWidth((short) 15);
            HSSFCellStyle headerStyle = workbook.createCellStyle();

            // 设置表头样式
            headerStyle.setBorderBottom(BorderStyle.THIN);
            headerStyle.setBorderLeft(BorderStyle.THIN);
            headerStyle.setBorderRight(BorderStyle.THIN);
            headerStyle.setBorderTop(BorderStyle.THIN);
            headerStyle.setAlignment(HorizontalAlignment.CENTER);

            HSSFFont headerFont = workbook.createFont();
            headerFont.setBold(true);
            headerFont.setFontHeightInPoints((short) 12);
            headerStyle.setFont(headerFont);

            // 设置内容样式
            HSSFCellStyle contentStyle = workbook.createCellStyle();
            contentStyle.setBorderBottom(BorderStyle.THIN);
            contentStyle.setBorderLeft(BorderStyle.THIN);
            contentStyle.setBorderRight(BorderStyle.THIN);
            contentStyle.setBorderTop(BorderStyle.THIN);
            contentStyle.setAlignment(HorizontalAlignment.CENTER);
            contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            HSSFFont contentFont = workbook.createFont();
            contentFont.setBold(false);
            contentStyle.setFont(contentFont);

            // 日期单元格样式
            CreationHelper createHelper = workbook.getCreationHelper();
            CellStyle dateStyle = workbook.createCellStyle();
            dateStyle.cloneStyleFrom(contentStyle);
            dateStyle.setDataFormat(createHelper.createDataFormat().getFormat(dateFormat));

            CellStyle simpleDateStyle = workbook.createCellStyle();
            simpleDateStyle.setDataFormat(createHelper.createDataFormat().getFormat(dateFormat));

            HSSFRow row;
            HSSFCell cell;
            HSSFRichTextString richString;
            int index;

            // 在显示数据集合之前提前显示几行数据List<List<Object>> firstFewRows
            if (firstFewRows != null && !firstFewRows.isEmpty()) {
                for (List<Object> cells : firstFewRows) {
                    // Rows are 0 based.
                    row = sheet.createRow(currentRowCount - 1);
                    currentRowCount++;

                    index = 0;
                    for (Object value : cells) {
                        cell = row.createCell(index++);

                        if (value == null) {
                            continue;
                        } else if (value instanceof String) {
                            cell.setCellValue((String) value);
                        } else if (value instanceof Date) {
                            cell.setCellValue((Date) value);
                            cell.setCellStyle(simpleDateStyle);
                        } else {
                            richString = new HSSFRichTextString(JSONObject.toJSONString(value));
                            cell.setCellValue(richString);
                        }
                    }
                }
            }

            // 产生表格标题行
            row = sheet.createRow(currentRowCount - 1);
            currentRowCount++;

            index = 0;
            for (String text : headers) {
                cell = row.createCell(index++);
                cell.setCellStyle(headerStyle);
                richString = new HSSFRichTextString(text);
                cell.setCellValue(richString);
            }

            // 遍历集合数据，产生数据行
            Object value;

            for (Map<String, Object> dataMap : datas) {
                if (currentRowCount % perPageNum == 0) {
                    sheet = null;
                    sheetNum++;
                    safeTitle = WorkbookUtil.createSafeSheetName(title + "_" + sheetNum);
                    sheet = workbook.createSheet(safeTitle);
                    currentRowCount = 1;
                }

                row = sheet.createRow(currentRowCount - 1);
                currentRowCount++;

                index = 0;
                for (String column : dataColumns) {
                    value = dataMap.get(column);

                    cell = row.createCell(index++);
                    cell.setCellStyle(contentStyle);

                    if (value == null) {
                        continue;
                    } else if (value instanceof Integer) {
                        cell.setCellValue(Double.parseDouble(value.toString()));
                    } else if (value instanceof String) {
                        cell.setCellValue((String) value);
                    } else if (value instanceof Date) {
                        // 日期设置单独的样式
                        cell.setCellStyle(dateStyle);
                        cell.setCellValue((Date) value);
                    } else {
                        richString = new HSSFRichTextString(JSONObject.toJSONString(value));
                        cell.setCellValue(richString);
                    }
                }
            }

            workbook.write(out);

        } catch (IOException e) {
            logger.error("export excel error:", e);
        } finally {
            try {
                workbook.close();
            } catch (IOException e) {
                logger.error("close workbook error!", e);
            }
        }
    }

    /**
     * Test
     */
    public static void main(String[] args) {
        List<List<Object>> firstFewRows = new ArrayList<>();
        // excel标题行
        String[] headers = new String[]{"物理机名称", "IPMI主机IP", "IPMI主机用户名", "IPMI主机密码", "制造商", "备注信息"};
        String[] dataColumns = new String[]{"name", "ipmiIp", "ipmiUser", "ipmiPassword", "manufacturer", "remark"};
        // 样例数据
        List<Map<String, Object>> allRows = new ArrayList<>();
        Map<String, Object> row = new HashMap<>(6);
        row.put(dataColumns[0], "浪潮服务器001");
        row.put(dataColumns[1], "192.168.2.2");
        row.put(dataColumns[2], "appadmin");
        row.put(dataColumns[3], "Alice@1234#***");
        row.put(dataColumns[4], "inspur");
        row.put(dataColumns[5], "文件服务器");
        allRows.add(row);

        row = new HashMap<>(6);
        row.put(dataColumns[0], "浪潮服务器002");
        row.put(dataColumns[1], "192.168.2.2");
        row.put(dataColumns[2], "appadmin");
        row.put(dataColumns[3], "Alice@5678#***");
        row.put(dataColumns[4], "inspur");
        row.put(dataColumns[5], "邮件服务器");
        allRows.add(row);

        // 文件名
        String timeStr = DateTools.formatTime2String(new Date(), "yyyy-MM-dd-HH-mm-ss");
        String fileName = "import-batch-physical-machine-template-" + timeStr + ".xls";

        try {
            OutputStream out = new FileOutputStream("D:/" + fileName);
            ExcelExporter.export("Sheet", firstFewRows, headers, dataColumns, allRows, out, "yyyy-MM-dd HH:mm:ss");
            out.flush();
            out.close();
        } catch (IOException e) {
            logger.error("export excel file fails.", e);
        }
    }

    //增加下拉框处理
    public static void azurePriceExport(String title, List<List<Object>> firstFewRows, String[] headers, String[] dataColumns,
                                        List<Map<String, Object>> datas, OutputStream out, String dateFormat,
                                        String[] regions) {
        if (null == headers || headers.length <= 0 || null == out) {
            logger.warn("no headers or OutputStream is null");
            return;
        }
        if (null == datas) {
            logger.info("no datas");
            datas = new ArrayList<>();
        }
        if (dateFormat.isEmpty()) {
            dateFormat = "yyyy-MM-dd";
        }

        HSSFWorkbook workbook = new HSSFWorkbook();

        try {
            int sheetNum = 1;
            int currentRowCount = 1;
            // 每个工作薄显示50000条数据(MAX:65536)
            int perPageNum = 50000;

            String safeTitle = WorkbookUtil.createSafeSheetName(title + "_" + sheetNum);
            HSSFSheet sheet = workbook.createSheet(safeTitle);
            sheet.setDefaultColumnWidth((short) 15);

            {
                String dataSheetName = "数据源";
                Sheet dictDataSheet = workbook.createSheet(dataSheetName);
                String[] productType = {"STORAGE", "EIP"};
                String[] sType = {"Standard_LRS", "StandardSSD_LRS", "Premium_LRS"};
                String[] eType = {"Dynamic", "Static"};
                for (int i = 0; i < productType.length; i++) {
                    Row row = dictDataSheet.createRow(i);
                    Cell categoryCell = row.createCell(0);
                    categoryCell.setCellValue(productType[i]);
                    String[] resourceType;
                    if (productType[i].equalsIgnoreCase("STORAGE")) {
                        resourceType = sType;
                    } else {
                        resourceType = eType;
                    }
                    for (int j = 0; j < resourceType.length; j++) {
                        Cell cell = row.createCell(j + 1);
                        cell.setCellValue(resourceType[j]);
                    }
                    //对数据源添加名称函数
                    Name nameFunction = workbook.createName();
                    nameFunction.setNameName(productType[i]);
                    int index = i + 1;
                    int first = (productType.length + 1) / 26;
                    int second = (productType.length + 1) % 26;
                    StringBuilder charString = new StringBuilder();
                    if (first > 0) {
                        char firstChar = (char) ('A' + first);
                        char secondChar = (char) ('A' + second);
                        charString.append(firstChar).append(secondChar);
                    } else {
                        char firstChar = (char) ('A' + second);
                        charString.append(firstChar);
                    }
                    String string = dataSheetName + "!$B$" + index + ":$" + charString.toString() + "$" + index;
                    nameFunction.setRefersToFormula(string);
                }
                //加载下拉列表
                HSSFDataValidationHelper categoryValidationHelper = new HSSFDataValidationHelper(sheet);
                DataValidationConstraint categoryConstraint = categoryValidationHelper.createFormulaListConstraint("数据源!$A$1:$A$" + productType.length);
                CellRangeAddressList categoryList = new CellRangeAddressList(1, 50000, 0, 0);
                //数据有效性对象
                DataValidation categoryDataValidation = categoryValidationHelper.createValidation(categoryConstraint, categoryList);
                //设置输入错误提示信息
                categoryDataValidation.createErrorBox("非法输入", "不允许输入，请选取下拉值！");
                sheet.addValidationData(categoryDataValidation);

                HSSFDataValidationHelper deptValidationHelper = new HSSFDataValidationHelper(sheet);
                DataValidationConstraint deptConstraint = deptValidationHelper.createFormulaListConstraint("INDIRECT($A1)");
                CellRangeAddressList deptList = new CellRangeAddressList(1, 50000, 1, 1);
                //数据有效性对象
                DataValidation departDataValidation = deptValidationHelper.createValidation(deptConstraint, deptList);
                //设置输入错误提示信息
                departDataValidation.createErrorBox("非法输入", "不允许输入，请选取下拉值！");
                sheet.addValidationData(departDataValidation);
                workbook.setSheetHidden(workbook.getSheetIndex("数据源"), true);

            }
            {
                CellRangeAddressList typeList = new CellRangeAddressList(1, 50000, 2, 2);
                //加载下拉列表
                HSSFDataValidationHelper typeValidationHelper = new HSSFDataValidationHelper(sheet);
                DataValidationConstraint typeConstraint = typeValidationHelper.createExplicitListConstraint(regions);
                //数据有效性对象
                DataValidation typeDataValidation = typeValidationHelper.createValidation(typeConstraint, typeList);
                //设置输入错误提示信息
                typeDataValidation.createErrorBox("非法输入", "不允许输入，请选取下拉值！");
                sheet.addValidationData(typeDataValidation);
            }
            {
                //添加数据验证
                String[] type = {"Minutes", "Hours", "Months"};
                CellRangeAddressList typeList = new CellRangeAddressList(1, 50000, 6, 6);
                //加载下拉列表
                HSSFDataValidationHelper typeValidationHelper = new HSSFDataValidationHelper(sheet);
                DataValidationConstraint typeConstraint = typeValidationHelper.createExplicitListConstraint(type);
                //数据有效性对象
                DataValidation typeDataValidation = typeValidationHelper.createValidation(typeConstraint, typeList);
                //设置输入错误提示信息
                typeDataValidation.createErrorBox("非法输入", "不允许输入，请选取下拉值！");
                sheet.addValidationData(typeDataValidation);
            }
            //----------------------------------------------------------------

            HSSFCellStyle headerStyle = workbook.createCellStyle();
            // 设置表头样式
            headerStyle.setBorderBottom(BorderStyle.THIN);
            headerStyle.setBorderLeft(BorderStyle.THIN);
            headerStyle.setBorderRight(BorderStyle.THIN);
            headerStyle.setBorderTop(BorderStyle.THIN);
            headerStyle.setAlignment(HorizontalAlignment.CENTER);

            HSSFFont headerFont = workbook.createFont();
            headerFont.setBold(true);
            headerFont.setFontHeightInPoints((short) 12);
            headerStyle.setFont(headerFont);

            // 设置内容样式
            HSSFCellStyle contentStyle = workbook.createCellStyle();
            contentStyle.setBorderBottom(BorderStyle.THIN);
            contentStyle.setBorderLeft(BorderStyle.THIN);
            contentStyle.setBorderRight(BorderStyle.THIN);
            contentStyle.setBorderTop(BorderStyle.THIN);
            contentStyle.setAlignment(HorizontalAlignment.CENTER);
            contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            HSSFFont contentFont = workbook.createFont();
            contentFont.setBold(false);
            contentStyle.setFont(contentFont);

            // 日期单元格样式
            CreationHelper createHelper = workbook.getCreationHelper();
            CellStyle dateStyle = workbook.createCellStyle();
            dateStyle.cloneStyleFrom(contentStyle);
            dateStyle.setDataFormat(createHelper.createDataFormat().getFormat(dateFormat));

            CellStyle simpleDateStyle = workbook.createCellStyle();
            simpleDateStyle.setDataFormat(createHelper.createDataFormat().getFormat(dateFormat));

            HSSFRow row;
            HSSFCell cell;
            HSSFRichTextString richString;
            int index;

            // 在显示数据集合之前提前显示几行数据List<List<Object>> firstFewRows
            if (firstFewRows != null && !firstFewRows.isEmpty()) {
                for (List<Object> cells : firstFewRows) {
                    // Rows are 0 based.
                    row = sheet.createRow(currentRowCount - 1);
                    currentRowCount++;

                    index = 0;
                    for (Object value : cells) {
                        cell = row.createCell(index++);

                        if (value == null) {
                            continue;
                        } else if (value instanceof String) {
                            cell.setCellValue((String) value);
                        } else if (value instanceof Date) {
                            cell.setCellValue((Date) value);
                            cell.setCellStyle(simpleDateStyle);
                        } else {
                            richString = new HSSFRichTextString(JSONObject.toJSONString(value));
                            cell.setCellValue(richString);
                        }
                    }
                }
            }

            // 产生表格标题行
            row = sheet.createRow(currentRowCount - 1);
            currentRowCount++;

            index = 0;
            for (String text : headers) {
                cell = row.createCell(index++);
                cell.setCellStyle(headerStyle);
                richString = new HSSFRichTextString(text);
                cell.setCellValue(richString);
            }

            // 遍历集合数据，产生数据行
            Object value;

            for (Map<String, Object> dataMap : datas) {
                if (currentRowCount % perPageNum == 0) {
                    sheet = null;
                    sheetNum++;
                    safeTitle = WorkbookUtil.createSafeSheetName(title + "_" + sheetNum);
                    sheet = workbook.createSheet(safeTitle);
                    currentRowCount = 1;
                }

                row = sheet.createRow(currentRowCount - 1);
                currentRowCount++;

                index = 0;
                for (String column : dataColumns) {
                    value = dataMap.get(column);

                    cell = row.createCell(index++);
                    cell.setCellStyle(contentStyle);

                    if (value == null) {
                        continue;
                    } else if (value instanceof Integer) {
                        cell.setCellValue(Double.parseDouble(value.toString()));
                    } else if (value instanceof String) {
                        cell.setCellValue((String) value);
                    } else if (value instanceof Date) {
                        // 日期设置单独的样式
                        cell.setCellStyle(dateStyle);
                        cell.setCellValue((Date) value);
                    } else {
                        richString = new HSSFRichTextString(JSONObject.toJSONString(value));
                        cell.setCellValue(richString);
                    }
                }
            }

            workbook.write(out);

        } catch (IOException e) {
            logger.error("export excel error:", e);
        } finally {
            try {
                workbook.close();
            } catch (IOException e) {
                logger.error("close workbook error!", e);
            }
        }
    }

    //增加下拉框处理
    public static void azureFlavorExport(String title, List<List<Object>> firstFewRows, String[] headers, String[] dataColumns,
                                         List<Map<String, Object>> datas, OutputStream out, String dateFormat,
                                         String[] regions) {
        if (null == headers || headers.length <= 0 || null == out) {
            logger.warn("no headers or OutputStream is null");
            return;
        }
        if (null == datas) {
            logger.info("no datas");
            datas = new ArrayList<>();
        }
        if (dateFormat.isEmpty()) {
            dateFormat = "yyyy-MM-dd";
        }

        HSSFWorkbook workbook = new HSSFWorkbook();

        try {
            int sheetNum = 1;
            int currentRowCount = 1;
            // 每个工作薄显示50000条数据(MAX:65536)
            int perPageNum = 50000;

            String safeTitle = WorkbookUtil.createSafeSheetName(title + "_" + sheetNum);
            HSSFSheet sheet = workbook.createSheet(safeTitle);
            sheet.setDefaultColumnWidth((short) 15);
//            {
//                CellRangeAddressList typeList = new CellRangeAddressList(1, 50000, 1, 1);
//                //加载下拉列表
//                HSSFDataValidationHelper typeValidationHelper = new HSSFDataValidationHelper(sheet);
//                DataValidationConstraint typeConstraint = typeValidationHelper.createExplicitListConstraint(regions);
//                //数据有效性对象
//                DataValidation typeDataValidation = typeValidationHelper.createValidation(typeConstraint, typeList);
//                //设置输入错误提示信息
//                typeDataValidation.createErrorBox("非法输入", "不允许输入，请选取下拉值！");
//                sheet.addValidationData(typeDataValidation);
//            }
            //----------------------------------------------------------------

            HSSFCellStyle headerStyle = workbook.createCellStyle();
            // 设置表头样式
            headerStyle.setBorderBottom(BorderStyle.THIN);
            headerStyle.setBorderLeft(BorderStyle.THIN);
            headerStyle.setBorderRight(BorderStyle.THIN);
            headerStyle.setBorderTop(BorderStyle.THIN);
            headerStyle.setAlignment(HorizontalAlignment.CENTER);

            HSSFFont headerFont = workbook.createFont();
            headerFont.setBold(true);
            headerFont.setFontHeightInPoints((short) 12);
            headerStyle.setFont(headerFont);

            // 设置内容样式
            HSSFCellStyle contentStyle = workbook.createCellStyle();
            contentStyle.setBorderBottom(BorderStyle.THIN);
            contentStyle.setBorderLeft(BorderStyle.THIN);
            contentStyle.setBorderRight(BorderStyle.THIN);
            contentStyle.setBorderTop(BorderStyle.THIN);
            contentStyle.setAlignment(HorizontalAlignment.CENTER);
            contentStyle.setVerticalAlignment(VerticalAlignment.CENTER);

            HSSFFont contentFont = workbook.createFont();
            contentFont.setBold(false);
            contentStyle.setFont(contentFont);

            // 日期单元格样式
            CreationHelper createHelper = workbook.getCreationHelper();
            CellStyle dateStyle = workbook.createCellStyle();
            dateStyle.cloneStyleFrom(contentStyle);
            dateStyle.setDataFormat(createHelper.createDataFormat().getFormat(dateFormat));

            CellStyle simpleDateStyle = workbook.createCellStyle();
            simpleDateStyle.setDataFormat(createHelper.createDataFormat().getFormat(dateFormat));

            HSSFRow row;
            HSSFCell cell;
            HSSFRichTextString richString;
            int index;

            // 在显示数据集合之前提前显示几行数据List<List<Object>> firstFewRows
            if (firstFewRows != null && !firstFewRows.isEmpty()) {
                for (List<Object> cells : firstFewRows) {
                    // Rows are 0 based.
                    row = sheet.createRow(currentRowCount - 1);
                    currentRowCount++;

                    index = 0;
                    for (Object value : cells) {
                        cell = row.createCell(index++);

                        if (value == null) {
                            continue;
                        } else if (value instanceof String) {
                            cell.setCellValue((String) value);
                        } else if (value instanceof Date) {
                            cell.setCellValue((Date) value);
                            cell.setCellStyle(simpleDateStyle);
                        } else {
                            richString = new HSSFRichTextString(JSONObject.toJSONString(value));
                            cell.setCellValue(richString);
                        }
                    }
                }
            }

            // 产生表格标题行
            row = sheet.createRow(currentRowCount - 1);
            currentRowCount++;

            index = 0;
            for (String text : headers) {
                cell = row.createCell(index++);
                cell.setCellStyle(headerStyle);
                richString = new HSSFRichTextString(text);
                cell.setCellValue(richString);
            }

            // 遍历集合数据，产生数据行
            Object value;

            for (Map<String, Object> dataMap : datas) {
                if (currentRowCount % perPageNum == 0) {
                    sheet = null;
                    sheetNum++;
                    safeTitle = WorkbookUtil.createSafeSheetName(title + "_" + sheetNum);
                    sheet = workbook.createSheet(safeTitle);
                    currentRowCount = 1;
                }

                row = sheet.createRow(currentRowCount - 1);
                currentRowCount++;

                index = 0;
                for (String column : dataColumns) {
                    value = dataMap.get(column);

                    cell = row.createCell(index++);
                    cell.setCellStyle(contentStyle);

                    if (value == null) {
                        continue;
                    } else if (value instanceof Integer) {
                        cell.setCellValue(Double.parseDouble(value.toString()));
                    } else if (value instanceof String) {
                        cell.setCellValue((String) value);
                    } else if (value instanceof Date) {
                        // 日期设置单独的样式
                        cell.setCellStyle(dateStyle);
                        cell.setCellValue((Date) value);
                    } else {
                        richString = new HSSFRichTextString(JSONObject.toJSONString(value));
                        cell.setCellValue(richString);
                    }
                }
            }

            workbook.write(out);

        } catch (IOException e) {
            logger.error("export excel error:", e);
        } finally {
            try {
                workbook.close();
            } catch (IOException e) {
                logger.error("close workbook error!", e);
            }
        }
    }
}
