package com.njcn.utils;

import com.njcn.enums.LogTypeEnum;
import com.njcn.pojo.advanced.SagEvent;
import com.njcn.pojo.weeklyreport.AreaPointInfoData;
import com.njcn.pojo.weeklyreport.SagRateData;
import com.njcn.service.log.UserLogDetailService;
import org.apache.poi.ss.usermodel.HorizontalAlignment;
import org.apache.poi.ss.usermodel.VerticalAlignment;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.springframework.beans.factory.annotation.Autowired;
import sun.misc.BASE64Decoder;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.*;

public class WeeklyExcelUtil {
    @Autowired
    private UserLogDetailService userLog;
    // excel工作薄对象
    private XSSFWorkbook workbook;
    // 表单集合
    private List<XSSFSheet> listSheet;
    private List<byte[]> listPic;

    private XSSFCellStyle style1;
    private XSSFCellStyle style2;
    private XSSFCellStyle style3;
    private XSSFCellStyle defaultStyle;

    // 重写构造函数
    public WeeklyExcelUtil(String... sheetName) {
        workbook = new XSSFWorkbook();
        listSheet = new ArrayList<>();
        listPic = new ArrayList<>();

        for (int i = 0; i < sheetName.length; i++) {
            listSheet.add(workbook.createSheet(sheetName[i]));
        }

        // 设置单元格列宽
        Map<Integer, Integer> map1 = new HashMap<>();
        map1.put(0, 25);
        setColumnWidth(listSheet.get(0), map1);

        Map<Integer, Integer> map2 = new HashMap<>();
        map2.put(1, 25);
        map2.put(2, 20);
        map2.put(3, 20);
        map2.put(4, 20);
        map2.put(5, 25);
        map2.put(6, 20);
        map2.put(7, 20);
        setColumnWidth(listSheet.get(1), map2);

        Map<Integer, Integer> map3 = new HashMap<>();
        map3.put(1, 25);
        map3.put(2, 20);
        map3.put(3, 20);
        map3.put(4, 20);
        map3.put(5, 25);
        map3.put(6, 20);
        map3.put(7, 25);
        setColumnWidth(listSheet.get(3), map3);

        // 设置字体默认样式
        for (int i = 0; i < 4; i++) {
            setStyle(i);
        }
    }

    public List<byte[]> getListPic() {
        return listPic;
    }

    private XSSFCellStyle getStyle(int styleType) {
        switch (styleType) {
            case 0:
                return style1;
            case 1:
                return style2;
            case 3:
                return style3;
            default:
                return defaultStyle;
        }
    }

    private void setStyle(int styleType) {
        XSSFFont font = workbook.createFont();
        font.setFontName("微软雅黑");
        font.setFontHeightInPoints((short) 9);

        switch (styleType) {
            case 0:
                style1 = workbook.createCellStyle();
                font.setFontHeightInPoints((short) 11);
                font.setBold(true);
                style1.setVerticalAlignment(VerticalAlignment.CENTER);
                style1.setAlignment(HorizontalAlignment.CENTER_SELECTION);
                style1.setFont(font);
                break;
            case 1:
                style2 = workbook.createCellStyle();
                font.setFontHeightInPoints((short) 10);
                style2.setVerticalAlignment(VerticalAlignment.CENTER);
                style2.setAlignment(HorizontalAlignment.CENTER_SELECTION);
                font.setBold(true);
                style2.setFont(font);
                break;
            case 3:
                style3 = workbook.createCellStyle();
                style3.setVerticalAlignment(VerticalAlignment.CENTER);
                style3.setAlignment(HorizontalAlignment.CENTER_SELECTION);
                style3.setFont(font);
                break;
            default:
                defaultStyle = workbook.createCellStyle();
                defaultStyle.setVerticalAlignment(VerticalAlignment.CENTER);
                defaultStyle.setFont(font);
                break;
        }
    }

    public XSSFWorkbook getWorkbook() {
        return workbook;
    }

    public void setWorkbook(XSSFWorkbook workbook) {
        this.workbook = workbook;
    }

    public List<XSSFSheet> getListSheet() {
        return listSheet;
    }

    public void setListSheet(List<XSSFSheet> listSheet) {
        this.listSheet = listSheet;
    }

    // 默认构造函数
    public WeeklyExcelUtil() {
        super();
    }

    // 设置列宽
    private void setColumnWidth(XSSFSheet sheet, Map<Integer, Integer> map) {
        Set<Map.Entry<Integer, Integer>> sets = map.entrySet();
        for (Map.Entry<Integer, Integer> entry : sets) {
            sheet.setColumnWidth(entry.getKey().intValue(), entry.getValue().intValue() * 256);
        }
    }

    // 导出表格
    public void exportFile(XSSFWorkbook workbook, HttpServletResponse response, HttpServletRequest request) {
        try {
            response.setContentType("application/force-download");
            response.addHeader("Content-Disposition",
                    "attachment;fileName=" + new String(("电压暂降周报").getBytes("GB2312"), "iso8859-1") + ".xlsx");// 设置文件名
            OutputStream outputStream = response.getOutputStream();

            // 贴图(暂降总体概况)
            for (int i = 0, j = 0; i < listPic.size() - 1; i++, j += 13) {
                ByteArrayOutputStream outStreamdd = new ByteArrayOutputStream();
                BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(listPic.get(i)));
                ImageIO.write(bufferedImage, "PNG", outStreamdd);
                XSSFDrawing xssfDrawing = listSheet.get(0).createDrawingPatriarch();
                XSSFClientAnchor clientAnchor = new XSSFClientAnchor(1, 1, 1, 1, 4, j, 15, j + 12);
                xssfDrawing.createPicture(clientAnchor,
                        workbook.addPicture(outStreamdd.toByteArray(), XSSFWorkbook.PICTURE_TYPE_PNG));
            }

            // 贴图(暂降原因统计)
            ByteArrayOutputStream outStreamdd = new ByteArrayOutputStream();
            BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream(listPic.get(4)));
            ImageIO.write(bufferedImage, "PNG", outStreamdd);
            XSSFDrawing xssfDrawing = listSheet.get(2).createDrawingPatriarch();
            XSSFClientAnchor clientAnchor = new XSSFClientAnchor(1, 1, 1, 1, 0, 5, 5, 17);
            xssfDrawing.createPicture(clientAnchor,
                    workbook.addPicture(outStreamdd.toByteArray(), XSSFWorkbook.PICTURE_TYPE_PNG));

            workbook.write(outputStream);
            workbook.close();
            outputStream.close();
            userLog.getLog("暂态报表导出", "成功", PubUtils.getIpAddr(request), LogTypeEnum.BUSSINESS.toString(), 0);
        } catch (IOException e) {
            userLog.getLog("暂态报表导出", "失败", PubUtils.getIpAddr(request), LogTypeEnum.BUSSINESS.toString(), 0);
        }
    }

    @SuppressWarnings("unchecked")
    public void writePointInfo(XSSFSheet sheet, List<AreaPointInfoData>... list) {
        int rowId = 0;
        // 第一行
        XSSFRow row = sheet.createRow(rowId++);
        XSSFCell cell = row.createCell(0);
        setValue(cell, "暂降统计");
        cell.setCellStyle(this.getStyle(0));
        sheet.addMergedRegion(new CellRangeAddress(rowId - 1, rowId - 1, 0, 3));
        // 第二行
        row = sheet.createRow(rowId++);
        cell = row.createCell(0);
        setValue(cell, "按区域统计");
        cell.setCellStyle(this.getStyle(1));
        sheet.addMergedRegion(new CellRangeAddress(rowId - 1, rowId - 1, 0, 3));
        // 第三行
        row = sheet.createRow(rowId++);
        cell = row.createCell(0);
        setValue(cell, "区域");
        cell.setCellStyle(this.getStyle(1));
        cell = row.createCell(1);
        setValue(cell, "监测点数量");
        cell.setCellStyle(this.getStyle(1));
        sheet.addMergedRegion(new CellRangeAddress(rowId - 1, rowId - 1, 1, 2));
        cell = row.createCell(3);
        setValue(cell, "暂降次数");
        cell.setCellStyle(this.getStyle(1));
        // 第四行
        row = sheet.createRow(rowId++);
        sheet.addMergedRegion(new CellRangeAddress(rowId - 2, rowId - 1, 0, 0));
        cell = row.createCell(1);
        setValue(cell, "在线");
        cell.setCellStyle(this.getStyle(1));
        cell = row.createCell(2);
        setValue(cell, "离线");
        cell.setCellStyle(this.getStyle(1));
        sheet.addMergedRegion(new CellRangeAddress(rowId - 2, rowId - 1, 3, 3));

        for (int i = 0; i < list[0].size(); i++) {
            row = sheet.createRow(rowId++);
            cell = row.createCell(0);
            setValue(cell, list[0].get(i).getName());
            cell.setCellStyle(this.getStyle(3));
            cell = row.createCell(1);
            setValue(cell, list[0].get(i).getOnLine());
            cell.setCellStyle(this.getStyle(3));
            cell = row.createCell(2);
            setValue(cell, list[0].get(i).getOffLine());
            cell.setCellStyle(this.getStyle(3));
            cell = row.createCell(3);
            setValue(cell, list[0].get(i).getEventCount());
            cell.setCellStyle(this.getStyle(3));
        }

        // 电压等级数据
        // 第二行
        row = sheet.createRow(rowId++);
        cell = row.createCell(0);
        setValue(cell, "按电压等级统计");
        cell.setCellStyle(this.getStyle(1));
        sheet.addMergedRegion(new CellRangeAddress(rowId - 1, rowId - 1, 0, 3));
        // 第三行
        row = sheet.createRow(rowId++);
        cell = row.createCell(0);
        setValue(cell, "电压等级");
        cell.setCellStyle(this.getStyle(1));
        cell = row.createCell(1);
        setValue(cell, "监测点数量");
        cell.setCellStyle(this.getStyle(1));
        sheet.addMergedRegion(new CellRangeAddress(rowId - 1, rowId - 1, 1, 2));
        cell = row.createCell(3);
        setValue(cell, "暂降次数");
        cell.setCellStyle(this.getStyle(1));
        // 第四行
        row = sheet.createRow(rowId++);
        sheet.addMergedRegion(new CellRangeAddress(rowId - 2, rowId - 1, 0, 0));
        cell = row.createCell(1);
        setValue(cell, "在线");
        cell.setCellStyle(this.getStyle(1));
        cell = row.createCell(2);
        setValue(cell, "离线");
        cell.setCellStyle(this.getStyle(1));
        sheet.addMergedRegion(new CellRangeAddress(rowId - 2, rowId - 1, 3, 3));

        for (int i = 0; i < list[1].size(); i++) {
            row = sheet.createRow(rowId++);
            cell = row.createCell(0);
            setValue(cell, list[1].get(i).getName());
            cell.setCellStyle(this.getStyle(3));
            cell = row.createCell(1);
            setValue(cell, list[1].get(i).getOnLine());
            cell.setCellStyle(this.getStyle(3));
            cell = row.createCell(2);
            setValue(cell, list[1].get(i).getOffLine());
            cell.setCellStyle(this.getStyle(3));
            cell = row.createCell(3);
            setValue(cell, list[1].get(i).getEventCount());
            cell.setCellStyle(this.getStyle(3));
        }
    }

    public void writeSagData(XSSFSheet sheet, List<SagEvent> list, int type) {
        int rowId = 0;
        // 第一行
        XSSFRow row = sheet.createRow(rowId++);
        XSSFCell cell = row.createCell(0);
        String tableName = "暂降严重度(前二十)";
        short lastColumn = 7;

        if (type == 2) {
            tableName = "暂降事件列表";
        }
        setValue(cell, tableName);
        cell.setCellStyle(this.getStyle(0));
        sheet.addMergedRegion(new CellRangeAddress(rowId - 1, rowId - 1, 0, lastColumn));
        String[] arr = {"序号", "暂降发生时刻", "供电公司", "变电站", "监测点", "暂降(骤升)幅值(%)", "持续时间(s)"};

        if (type == 2) {
            arr = Arrays.copyOf(arr, arr.length + 1);
            arr[arr.length - 1] = "暂降类型(机器判断)";
        } else {
            arr = Arrays.copyOf(arr, arr.length + 1);
            arr[arr.length - 1] = "暂降严重度";
        }

        // 第二行
        row = sheet.createRow(rowId++);
        for (int i = 0; i < arr.length; i++) {
            cell = row.createCell(i);
            setValue(cell, arr[i]);
            cell.setCellStyle(this.getStyle(1));
        }

        for (int i = 0; i < list.size(); i++) {
            row = sheet.createRow(rowId++);
            cell = row.createCell(0);
            setValue(cell, i + 1);
            cell.setCellStyle(this.getStyle(3));
            cell = row.createCell(1);
            setValue(cell, list.get(i).getStrTime());
            cell.setCellStyle(this.getStyle(3));
            cell = row.createCell(2);
            setValue(cell, list.get(i).getPlantInfo().getNameGD());
            cell.setCellStyle(this.getStyle(3));
            cell = row.createCell(3);
            setValue(cell, list.get(i).getPlantInfo().getNameBD());
            cell.setCellStyle(this.getStyle(3));
            cell = row.createCell(4);
            setValue(cell, list.get(i).getPlantInfo().getNamePoint());
            cell.setCellStyle(this.getStyle(3));
            cell = row.createCell(5);
            setValue(cell, list.get(i).getEventValue());
            cell.setCellStyle(this.getStyle(3));
            cell = row.createCell(6);
            setValue(cell, list.get(i).getPersistTime(), 1000);
            cell.setCellStyle(this.getStyle(3));

            if (type == 2) {
                cell = row.createCell(7);
                setValue(cell, list.get(i).getSagTypeDes());
                cell.setCellStyle(this.getStyle(3));
            } else {
                cell = row.createCell(7);
                setValue(cell, list.get(i).getSeverity());
                cell.setCellStyle(this.getStyle(3));
            }
        }
    }

    public void writeSagReason(XSSFSheet sheet, List<SagRateData> list) {
        int rowId = 0;
        // 第一行
        XSSFRow row = sheet.createRow(rowId++);
        XSSFCell cell = row.createCell(0);
        setValue(cell, "暂降原因统计表");
        cell.setCellStyle(this.getStyle(0));
        sheet.addMergedRegion(new CellRangeAddress(rowId - 1, rowId - 1, 0, list.size()));

        // 第二行
        row = sheet.createRow(rowId++);
        cell = row.createCell(0);
        setValue(cell, "暂降原因");
        cell.setCellStyle(this.getStyle(1));

        for (int i = 0; i < list.size(); i++) {
            cell = row.createCell(i + 1);
            setValue(cell, list.get(i).getName());
            cell.setCellStyle(this.getStyle(1));
            this.getListSheet().get(2).setColumnWidth(i + 1, 25 * 256);
        }

        // 第三行
        row = sheet.createRow(rowId++);
        cell = row.createCell(0);
        setValue(cell, "次数");
        cell.setCellStyle(this.getStyle(1));

        for (int i = 0; i < list.size(); i++) {
            cell = row.createCell(i + 1);
            setValue(cell, list.get(i).getCount());
            cell.setCellStyle(this.getStyle(3));
        }

        // 第四行
        row = sheet.createRow(rowId++);
        cell = row.createCell(0);
        setValue(cell, "占比(%)");
        cell.setCellStyle(this.getStyle(1));

        for (int i = 0; i < list.size(); i++) {
            cell = row.createCell(i + 1);
            setValue(cell, list.get(i).getRate());
            cell.setCellStyle(this.getStyle(3));
        }
    }

    // 解析图片流
    public void translate(String... strPic) {
        // 判断数据是否为空
        BASE64Decoder decoder = new BASE64Decoder();

        // 生成图片
        for (int i = 0; i < strPic.length; i++) {
            try {
                byte[] buffer = decoder.decodeBuffer(strPic[i]);
                listPic.add(buffer);
            } catch (Exception e) {
                // log日志记录
            }
        }
    }

    private void setValue(XSSFCell cell, Object object, int... a) { //暂时处理
        if (object instanceof Float) {
            float f = ((Float) object).floatValue();
            int k = a.length > 0 ? a[0] : 100;
            float f1 = (float) (Math.round(f * k)) / k;
            cell.setCellValue(Double.parseDouble(String.valueOf(f1)));
            return;
        } else if (object instanceof Integer) {
            cell.setCellValue(((Integer) object).intValue());
            return;
        }

        cell.setCellValue(object.toString());
    }
}
