package com.persagy.framework.util;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.List;

import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.DateUtil;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.WorkbookFactory;

/**
 * @Description excel上传下载
 * @Author feng
 * @Date 2018/7/11 15:45
 * @Version 1.0
 */
public class ExcelUtils {
    /**
     * Description: 根据List集合数据生成.xlsx表格文件
     * @param dirPath 需要生成表格文件所在文件夹
     * @param fileName 需要生成表格文件的名称（不包含.后缀名）
     * @param sheetName 生成表格sheet页的名称
     * @param columnDataList 集合数据，一维数据为列数据 [["1行1列", "2行1列", "3行1列"], ["2行1列", "2行2列", "3行2列"]]
     * @throws Exception void
     * @author cuixubin
     * @since 2018年10月9日: 上午10:17:54
     */
	public static void createExcelUseListData(String dirPath, String fileName, List<List<Object>> columnDataList,
			String sheetName) throws Exception {

		if (StringUtils.isBlank(sheetName)) {
			throw new Exception("sheetName不能为空");
		}
		// 创建excel对象
		HSSFWorkbook workbook = new HSSFWorkbook();
		HSSFSheet sheet = workbook.createSheet(sheetName);
		// 输出流
		OutputStream out = null;
		try {
			File dir = new File(dirPath);
			// 如果目录不存在
			if (!dir.exists()) {
				if (!dir.mkdirs()) {
					throw new Exception("创建目录异常");
				}
			}
			if (columnDataList != null && !columnDataList.isEmpty()) {
				// 表格列数
				int columnNum = columnDataList.size();
				// 将数据设置到sheet对应的单元格中
				for (int i = 0; i < columnNum; i++) {
					List<Object> obj = columnDataList.get(i);
					// 遍历每一列
					for (int j = 0; j < obj.size(); j++) {
						HSSFRow row = sheet.getRow(j);
						// 如果该行有数据，则表示已经创建过，否则重新创建
						if (row == null) {
							row = sheet.createRow(j);
						}
						// 设置单元格的值
						HSSFCell cell = row.createCell(i, HSSFCell.CELL_TYPE_STRING);
						if (!"".equals(obj.get(j)) && obj.get(j) != null) {
							cell.setCellValue(obj.get(j).toString());
						}
					}
				}
			}
			String filePath = dirPath + File.separator + fileName + ".xlsx";
			// 输出流
			out = new FileOutputStream(new File(filePath));
			// 写入工作簿
			workbook.write(out);
		} finally {
			if (out != null) {
				out.flush();
				out.close();
			}
			if (workbook != null) {
				workbook.close();
			}
		}
	}

    /**
     * description 读取excel模版 将数据写入excel
     *
     * @param excelTemplateStream excel标签模版输入流
     * @param sheetName           标签名称
     * @param skipRows            跳过的行数 (从多少行之后开始写入)
     * @param skipColumns         跳过的列数 (从多少列之后开始写入)
     * @param filePath            生成的excel文件的path
     * @param rowInfoList         行数据的集合
     * @return void
     * @author feng
     * @since 17:35 2018/7/11
     */
    public static void writeInfoToExcel(InputStream excelTemplateStream, String sheetName, int skipRows, int skipColumns,
                                        String filePath, List<List<String>> rowInfoList) throws Exception {
        // 根据模板，创建工作簿
        Workbook workBook = null;
        // 输出流
        OutputStream out = null;
        try {
            workBook = WorkbookFactory.create(excelTemplateStream);
            Sheet sheet = workBook.getSheet(sheetName);
            // 输出流
            out = new FileOutputStream(new File(filePath));
            for (int rowNumber = 0; rowNumber < rowInfoList.size(); rowNumber++) {
                for (int columnNumber = 0; columnNumber < rowInfoList.get(rowNumber).size(); columnNumber++) {
                    createCell(workBook, sheet, rowNumber + skipRows, columnNumber + skipColumns, rowInfoList.get(rowNumber).get(columnNumber));
                }
            }
            workBook.write(out);
        } finally {
            if (out != null) {
                out.flush();
                out.close();
            }
            if (workBook != null) {
                workBook.close();
            }
        }
    }
    
    /**
     * Description: 将excel的sheet页数据转换成list
     * @param sheet
     * @param lastColumnNum 指定读取的最大列号，为null则获取sheet页行数据最长的列
     * @return [[第一行第一元素，第一行第二元素],[第二行第一元素，第二行第二元素]]
     * @throws Exception List<List<String>>
     * @author cuixubin
     * @since 2018年9月25日: 下午2:07:36
     * Update By cuixubin 2018年9月25日: 下午2:07:36
     */
    public static List<List<String>> sheetToList(Sheet sheet, Integer lastColumnNum) throws Exception {
    	List<List<String>> resultInfo = new ArrayList<>();
    	
		if (sheet == null) {
			return null;
		}
		
		if(null == lastColumnNum) {
			for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
				Row row = sheet.getRow(rowNum);
				if (row == null) {
					continue;
				}
				if (lastColumnNum < row.getLastCellNum()) {
					lastColumnNum = row.getLastCellNum() + 0;
				}
			}
		}
		
		for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
			Row row = sheet.getRow(rowNum);
			ArrayList<String> curarr = new ArrayList<>();
			if (row == null) {
				for (int columnNum = 0; columnNum < lastColumnNum; columnNum++) {
					curarr.add(null);
				}
			} else {
				for (int columnNum = 0; columnNum < lastColumnNum; columnNum++) {
					Cell cell = row.getCell(columnNum);
					curarr.add(getCellStringValue(cell));
				}
			}
			resultInfo.add(curarr);
		}

		return resultInfo;

    }
    
    /**
     * description 读取excel信息
     *
     * @param in        文件输入流
     * @param sheetName sheet名称
     * @return java.util.List<java.util.List<java.lang.String>> 行信息的集合
     * @author feng
     * @since 16:16 2018/7/11
     */
    public static List<List<String>> getExcelSheetInfo(File exlFile, String sheetName) throws Exception {
    	List<List<String>> resultInfo = new ArrayList<>();
    	
    	try (Workbook workBook = WorkbookFactory.create(exlFile);){
    		// 遍历excel中的sheet
    		Sheet sheet = workBook.getSheet(sheetName);
    		if (sheet == null) {
    			return null;
    		}
    		
    		int lastColumnNum = 0;
    		for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
    			Row row = sheet.getRow(rowNum);
    			if (row == null) {
    				continue;
    			}
    			if (lastColumnNum < row.getLastCellNum()) {
    				lastColumnNum = row.getLastCellNum();
    			}
    		}
    		
    		for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
    			Row row = sheet.getRow(rowNum);
    			ArrayList<String> curarr = new ArrayList<>();
    			if (row == null) {
    				for (int columnNum = 0; columnNum < lastColumnNum; columnNum++) {
    					curarr.add("");
    				}
    			} else {
    				for (int columnNum = 0; columnNum < lastColumnNum; columnNum++) {
    					Cell cell = row.getCell(columnNum);
    					curarr.add(getCellStringValue(cell));
    				}
    			}
    			resultInfo.add(curarr);
    		}
    	}
        return resultInfo;

    }

    /**
     * description 读取excel信息
     *
     * @param in        文件输入流
     * @param sheetName sheet名称
     * @return java.util.List<java.util.List<java.lang.String>> 行信息的集合
     * @author feng
     * @since 16:16 2018/7/11
     */
    public static List<List<String>> getExcelSheetInfo(InputStream in, String sheetName) throws Exception {
        Workbook workBook = WorkbookFactory.create(in);
        // 遍历excel中的sheet
        List<List<String>> resultInfo = new ArrayList<>();
        Sheet sheet = workBook.getSheet(sheetName);
        if (sheet == null) {
            return null;
        }

        int lastColumnNum = 0;
        for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
            Row row = sheet.getRow(rowNum);
            if (row == null) {
                continue;
            }
            if (lastColumnNum < row.getLastCellNum()) {
                lastColumnNum = row.getLastCellNum();
            }
        }

        for (int rowNum = 0; rowNum <= sheet.getLastRowNum(); rowNum++) {
            Row row = sheet.getRow(rowNum);
            ArrayList<String> curarr = new ArrayList<>();
            if (row == null) {
                for (int columnNum = 0; columnNum < lastColumnNum; columnNum++) {
                    curarr.add("");
                }
            } else {
                for (int columnNum = 0; columnNum < lastColumnNum; columnNum++) {
                    Cell cell = row.getCell(columnNum);
                    curarr.add(getCellStringValue(cell));
                }
            }
            resultInfo.add(curarr);
        }
        return resultInfo;

    }

    public static void createCell(Workbook workbook, Sheet sheet, int rowNumber, int cellNumber, String content) {

        Row row = sheet.getRow(rowNumber);
        if (row == null) {
            row = sheet.createRow(rowNumber);
        }

        Cell cell = row.getCell(cellNumber);
        if (cell == null) {
            cell = row.createCell(cellNumber);
        }

        CellStyle cellStyle = workbook.createCellStyle();
        cellStyle.setAlignment(CellStyle.ALIGN_CENTER);
        cellStyle.setVerticalAlignment(CellStyle.VERTICAL_CENTER);

        cell.setCellStyle(cellStyle);
        if (content == null) {
            content = "";
        }
        cell.setCellValue(content);
    }

    /**
     * 
     * Description: 创建单元格并写入单元格内容（不设置单元格的格式，比createCell方法耗时短，速度快）
     * @param workbook
     * @param sheet
     * @param rowNumber 行数
     * @param cellNumber 列数
     * @param content 
     * @author JiShaoJun
     * @since 2019年3月6日: 上午10:29:08
     */
    public static void createCellNoStyle(Workbook workbook, Sheet sheet, int rowNumber, int cellNumber, String content) {
    	Row row = sheet.getRow(rowNumber);
    	if (row == null) {
            row = sheet.createRow(rowNumber);
        }
    	 Cell cell = row.getCell(cellNumber);
         if (cell == null) {
             cell = row.createCell(cellNumber);
         }
        if (content == null) {
            content = "";
        }
        cell.setCellValue(content);
    }
    
    public static String getCellStringValue(Cell cell) throws Exception {
        if (cell == null) {
            return "";
        }
        String value;
        switch (cell.getCellType()) {
            case Cell.CELL_TYPE_STRING:
                value = cell.getStringCellValue();
                break;
            case Cell.CELL_TYPE_NUMERIC:
                if (DateUtil.isCellDateFormatted(cell)) {
                    value = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(cell.getDateCellValue());
                } else {
                    value = new BigDecimal(Double.toString(cell.getNumericCellValue())).longValue() + "";
                }
                break;
            case Cell.CELL_TYPE_BOOLEAN:
                value = String.valueOf(cell.getBooleanCellValue());
                break;
            case Cell.CELL_TYPE_BLANK:
                value = "";
                break;
            case Cell.CELL_TYPE_ERROR:
                throw new Exception("can not resolve this cell! CELL_TYPE_ERROR! ");
            case Cell.CELL_TYPE_FORMULA:
                value = cell.getCellFormula();
                break;
            default:
                value = cell.getStringCellValue();
                break;
        } 

        return value;
    }
    
    /**
     * Description: 将样式为config/bifunction/Item.xls文件转为config/bifunction/energyModelTemplate.xls格式
     * @param fromExl 文件物理路径地址
     * @param sheetNameOfFromExl sheet页名称
     * @throws Exception void
     * @author cuixubin
     * @since 2019年1月23日: 下午3:06:19
     */
    public static void GetBIItemTemplateFromStandardItemExl(String fromExl, String sheetNameOfFromExl) throws Exception {
    	File fromFile = new File(fromExl);
    	if(fromFile.exists() && fromFile.isFile() && (fromExl.endsWith("xls") || fromExl.endsWith("xlsx"))) {
    		List<List<String>> dataList = getExcelSheetInfo(fromFile, sheetNameOfFromExl);
    		
    		if(dataList !=null && !dataList.isEmpty()) {
    			List<EItemDTO> itemList = new ArrayList<>();
    			
    			int maxRow = 0;
    			
    			for(int rowIndex=0; rowIndex<dataList.size(); rowIndex++) {
    				for(int i=0; i<dataList.get(rowIndex).size(); i++) {
    					// 分项名
    					String nameStr = dataList.get(rowIndex).get(i);
    					if(nameStr != null && !"".equals(nameStr)) {
    						// 分项属性编码
    						String codeStr = dataList.get(rowIndex).get(i+1);
    						
    						EItemDTO eitem = new EItemDTO();
    						eitem.name = nameStr;
    						eitem.code = codeStr;
    						eitem.level = i / 2;
    						
    						itemList.add(eitem);
    						
    						maxRow = maxRow < (eitem.level + 1) ? (eitem.level + 1) : maxRow;
    						
    						break;
    					}
    				}
    			}
    			
    			List<List<Object>> dataList2 = new ArrayList<>();
    			for(int i=0; i<maxRow+2; i++) {
    				List<Object> iList = new ArrayList<>();
    				dataList2.add(iList);
    			}
    			
    			for(int rowIndex=0; rowIndex<itemList.size(); rowIndex++) {
    				EItemDTO eitem = itemList.get(rowIndex);
    				for(int column=0; column<dataList2.size(); column++) {
    					if(column == 0) {
    						dataList2.get(column).add("EI" + eitem.code + "001");
    					}else if(column == 1) {
    						dataList2.get(column).add("" + eitem.code);
    					}else {
    						String names = "";
    						if(column == eitem.level + 2) {
    							names = eitem.name;
    						}
    						dataList2.get(column).add(names);
    					}
    				}
    			}
    			
    			createExcelUseListData2("D:\\TEST", "item", dataList2, "Sheet1");
    			System.out.println("success. file:D:/TEST/item.xlsx");
    		}
    	}else {
    		System.out.println("文件[" + fromExl + "]找不到或格式错误或已损坏。");
    	}
    }
    
    private static void createExcelUseListData2(String dirPath, String fileName, List<List<Object>> columnDataList,
			String sheetName) throws Exception {

		if (StringUtils.isBlank(sheetName)) {
			throw new Exception("sheetName不能为空");
		}
		// 创建excel对象
		HSSFWorkbook workbook = new HSSFWorkbook();
		HSSFSheet sheet = workbook.createSheet(sheetName);
		// 输出流
		OutputStream out = null;
		try {
			File dir = new File(dirPath);
			// 如果目录不存在
			if (!dir.exists()) {
				if (!dir.mkdirs()) {
					throw new Exception("创建目录异常");
				}
			}
			if (columnDataList != null && !columnDataList.isEmpty()) {
				// 表格列数
				int columnNum = columnDataList.size();
				// 将数据设置到sheet对应的单元格中
				for (int i = 0; i < columnNum; i++) {
					List<Object> obj = columnDataList.get(i);
					// 遍历每一列
					for (int j = 0; j < obj.size(); j++) {
						HSSFRow row = sheet.getRow(j);
						// 如果该行有数据，则表示已经创建过，否则重新创建
						if (row == null) {
							row = sheet.createRow(j);
						}
						// 设置单元格的值
						HSSFCell cell = row.createCell(i, HSSFCell.CELL_TYPE_STRING);
						if (obj.get(j) != null) {
							cell.setCellValue(obj.get(j).toString());
						}
					}
				}
			}
			String filePath = dirPath + File.separator + fileName + ".xlsx";
			// 输出流
			out = new FileOutputStream(new File(filePath));
			// 写入工作簿
			workbook.write(out);
		} finally {
			if (out != null) {
				out.flush();
				out.close();
			}
			if (workbook != null) {
				workbook.close();
			}
		}
	}
}



class EItemDTO {
	public String name;
	public String code;
	public int level;
	@Override
	public String toString() {
		return "[level=" + level + ", code=" + code + ", name=" + name + "]";
	}
	
}
