package com.bocloud.ims.service.utils;

import java.io.IOException;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.poifs.filesystem.NPOIFSFileSystem;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellType;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;

import com.google.common.base.Preconditions;

/**
 * Excel工作类
 *
 * @author sxp
 * @since 2017/11/13
 */
public class ExcelUtils {
    private static Logger logger = Logger.getLogger(ExcelUtils.class.getName());

    /**
     * 读取Excel文件的内容
     *
     * @param is
     *            Excel文件的输入流
     * @param ignoreFirstRow
     *            是否忽略第一行数据，如果第一样为标题行该参数应设置为true
     * @param columns
     *            数据的列名，用于返回值中Map的key值
     * @author sxp
     * @since 2017/11/13
     */
    @SuppressWarnings("deprecation")
    public static List<Map<String, Object>> readContent(InputStream is, boolean ignoreFirstRow, String[] columns) {
        Preconditions.checkNotNull(is, "is");

        List<Map<String, Object>> rows = new ArrayList<>();
        Map<String, Object> rowData;

        NPOIFSFileSystem fs = null;
        HSSFWorkbook wb = null;

        try {
            fs = new NPOIFSFileSystem(is);
            wb = new HSSFWorkbook(fs.getRoot(), true);
        } catch (IOException e) {
            logger.warning("读取Excel文件时出错:" + e.getMessage());
            closeResource(fs, wb, is);
            return rows;
        }

        SimpleDateFormat timeSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        int rowNum;
        int columnNum;
        CellType cellType;
        Object cellValue;
        Sheet sheet;

        try {
            // 只支持一个Sheet
            sheet = wb.getSheetAt(0);
        } catch (IllegalArgumentException e) {
            logger.log(Level.WARNING, "读取Excel文件时出错", e);
            closeResource(fs, wb, is);
            return rows;
        }

        rowNum = 0;
        for (Row row : sheet) {
            if (ignoreFirstRow && rowNum++ == 0) {
                continue;
            }

            rowData = new HashMap<>(columns.length);
            columnNum = 0;

            for (Cell cell : row) {
                // Will be renamed to <code>getCellType()</code>
                // 这个不赞成使用的方法目前没有替代方法使用
                cellType = cell.getCellTypeEnum();

                switch (cellType) {
                case ERROR:
                case BLANK:
                    cellValue = "";
                    break;
                case BOOLEAN:
                    cellValue = cell.getBooleanCellValue();
                    break;
                case NUMERIC:
                    if (HSSFDateUtil.isCellDateFormatted(cell)) {
                        cellValue = timeSdf.format(cell.getDateCellValue());
                    } else {
                        cellValue = cell.getNumericCellValue();
                    }
                    break;
                default:
                    cellValue = cell.getStringCellValue();
                    break;
                }

                rowData.put(columns[columnNum++], cellValue);
                if (columnNum >= columns.length) {
                    break;
                }
            }

            rows.add(rowData);
        }

        closeResource(fs, wb, is);
        return rows;
    }

    private static void closeResource(NPOIFSFileSystem fs, HSSFWorkbook wb, InputStream is) {
        try {
            if (wb != null) {
                wb.close();
            }
            if (fs != null) {
                fs.close();
            }
            if (is != null) {
                is.close();
            }
        } catch (IOException e) {
            logger.warning("关闭Excel资源时出错:" + e.getMessage());
        }
    }
}
