package com.mortals.xhx.common.excel.core;


import com.mortals.xhx.common.excel.annotation.ExcelAttribute;
import com.mortals.xhx.common.excel.annotation.ExcelElement;
import com.mortals.xhx.common.excel.annotation.ExcelID;
import com.mortals.xhx.common.excel.config.ElementTypePath;
import lombok.SneakyThrows;
import org.apache.poi.POIXMLDocumentPart;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.xssf.usermodel.*;
import org.openxmlformats.schemas.drawingml.x2006.spreadsheetDrawing.CTMarker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
import java.util.*;

/**
 * @描述
 * @创建人 zxfei
 * @创建时间 2021/3/4
 * @修改人和其它信息
 */
public class ExcelUtils<T> extends AbstractExcelUtilss<T> {

    public static String[] strs = {"A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L"
            , "M", "N", "O", "P", "Q", "R", "S", "T", "U", "V", "W", "X", "Y", "AA", "AB", "AC", "AD", "AE", "AF", "AG"};

    private Logger logger = LoggerFactory.getLogger(ExcelUtils.class);

    private Class<T> clazz;

    private HSSFRow row;

    private boolean flag;

    {
        flag = true;
    }

    @Override
    public IExcelUtil<T> build(Class<T> clazz) {
        this.clazz = clazz;
        return this;
    }


    @SneakyThrows
    @Override
    public void createHeader(HSSFWorkbook wb, HSSFSheet sheet, Map<String, String> configFieldMap) {
        // 产生一行
        HSSFRow row = ExcelTool.createRow(sheet);
        HSSFCellStyle style = wb.createCellStyle();

        HSSFPalette customPalette = wb.getCustomPalette();
        customPalette.setColorAtIndex(IndexedColors.LIGHT_BLUE.getIndex(), (byte) 80,
                (byte) 120, (byte) 203);

        style.setFillForegroundColor(HSSFColor.LIGHT_BLUE.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);

        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);

        style.setBottomBorderColor(IndexedColors.GREEN.getIndex());
        style.setLeftBorderColor(IndexedColors.GREEN.getIndex());
        style.setRightBorderColor(IndexedColors.GREEN.getIndex());
        style.setTopBorderColor(IndexedColors.GREEN.getIndex());



        style.setAlignment(CellStyle.ALIGN_CENTER);
        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        style.setWrapText(true);

        //设置字体
        HSSFFont font = wb.createFont();
        font.setFontHeightInPoints((short) 14); // 字体高度
        font.setFontName(" 微软雅黑 "); // 字体
        font.setColor(HSSFColor.WHITE.index);
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        style.setFont(font);

        // 得到所有的字段
        List<Field> fields = getAllField(clazz, null);
        int col = 0;
        HSSFCell cell;// 产生单元格
        for (Field field : fields) {
            ExcelAttribute attr = field.getAnnotation(ExcelAttribute.class);
            //int col = getExcelCol(attr.column());// 获得列号

            String colName = attr.name();
            if (configFieldMap.containsKey(colName)) {
                logger.info("colName before:" + colName);
                colName = configFieldMap.get(colName);
                logger.info("colName after:" + colName);
                //反射修改注解isExport值
                InvocationHandler h = Proxy.getInvocationHandler(attr);

                Field hField = h.getClass().getDeclaredField("memberValues");

                hField.setAccessible(true);
                // 获取 memberValues
                Map memberValues = (Map) hField.get(h);
                // 修改 value 属性值
                memberValues.put("isExport", true);
                //设置col值
                memberValues.put("column", strs[col]);
            }

            if (colName.startsWith("field") && attr.isExport()) {
                InvocationHandler h = Proxy.getInvocationHandler(attr);
                Field hField = h.getClass().getDeclaredField("memberValues");
                hField.setAccessible(true);
                // 获取 memberValues
                Map memberValues = (Map) hField.get(h);
                // 修改 value 属性值
                memberValues.put("isExport", false);
            }


            if (attr.isExport()) {
                logger.info("createcolName :" + colName);
                row.getSheet().setColumnWidth(col, Integer.parseInt(attr.colWidth()));
                cell = row.createCell(col);// 创建列
                cell.setCellType(HSSFCell.CELL_TYPE_STRING);// 设置列中写入内容为String类型
                cell.setCellValue(colName);// 写入列名

                // 如果设置了提示信息则鼠标 放上去提示.
                if (!attr.prompt().trim().equals("")) {
                    setHSSFPrompt(sheet, "", attr.prompt(), 1, 100, col, col);// 这里默认设了2-101列提示.
                }
                // 如果设置了combo属性则本列只能选择不能输入
                if (attr.combo().length > 0) {
                    setHSSFValidation(sheet, attr.combo(), 1, 100, col, col);// 这里默认设了2-101列只能选择不能输入.
                }
                cell.setCellStyle(style);
                col++;
            }

        }

    }

    @Override
    public void createHeaderFlat(HSSFWorkbook wb, HSSFSheet sheet, Map<String, String> configFieldMap) {
        // 产生第一行
        HSSFRow row = sheet.createRow(0);

        HSSFCellStyle style = wb.createCellStyle();

        HSSFPalette customPalette = wb.getCustomPalette();
        customPalette.setColorAtIndex(IndexedColors.YELLOW.getIndex(), (byte) 70,
                (byte) 112, (byte) 200);

        style.setBorderBottom(HSSFCellStyle.BORDER_THIN);
        style.setBorderLeft(HSSFCellStyle.BORDER_THIN);
        style.setBorderRight(HSSFCellStyle.BORDER_THIN);
        style.setBorderTop(HSSFCellStyle.BORDER_THIN);

        style.setBottomBorderColor(IndexedColors.GREEN.getIndex());
        style.setLeftBorderColor(IndexedColors.GREEN.getIndex());
        style.setRightBorderColor(IndexedColors.GREEN.getIndex());
        style.setTopBorderColor(IndexedColors.GREEN.getIndex());
        style.setFillForegroundColor(HSSFColor.YELLOW.index);
        style.setFillPattern(HSSFCellStyle.SOLID_FOREGROUND);
        style.setAlignment(CellStyle.ALIGN_CENTER);
        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        style.setWrapText(true);

        //设置字体
        HSSFFont font = wb.createFont();
        font.setFontHeightInPoints((short) 12); // 字体高度
        font.setFontName("微软雅黑"); // 字体
        font.setBoldweight(HSSFFont.BOLDWEIGHT_BOLD);
        font.setColor(HSSFColor.WHITE.index);
        style.setFont(font);

        // 得到所有的字段
        List<Field> fields = getAllField(clazz, null);
        int col = 0;
        HSSFCell cell;// 产生单元格
        for (Field field : fields) {
            ExcelAttribute attr = field.getAnnotation(ExcelAttribute.class);
            if ("BOM名称".equals(attr.name())) {
                row.getSheet().setColumnWidth(col, Integer.parseInt(attr.colWidth()));
                cell = row.createCell(getExcelCol(attr.column()));// 创建列
                cell.setCellType(HSSFCell.CELL_TYPE_STRING);// 设置列中写入内容为String类型
                cell.setCellValue(attr.name());// 写入列名
                cell.setCellStyle(style);
                logger.info("createcolName :" + attr.name());
                break;
            }
        }

        // 产生第二行
        row = sheet.createRow(1);
        for (Field field : fields) {
            ExcelAttribute attr = field.getAnnotation(ExcelAttribute.class);
            if ("创建日期".equals(attr.name())) {
                row.getSheet().setColumnWidth(col, Integer.parseInt(attr.colWidth()));
                cell = row.createCell(getExcelCol(attr.column()));// 创建列
                cell.setCellType(HSSFCell.CELL_TYPE_STRING);// 设置列中写入内容为String类型
                cell.setCellValue(attr.name());// 写入列名
                cell.setCellStyle(style);
                logger.info("createcolName :" + attr.name());
                continue;
            }
            if ("创建人".equals(attr.name())) {
                row.getSheet().setColumnWidth(col, Integer.parseInt(attr.colWidth()));
                cell = row.createCell(getExcelCol(attr.column()));// 创建列
                cell.setCellType(HSSFCell.CELL_TYPE_STRING);// 设置列中写入内容为String类型
                cell.setCellValue(attr.name());// 写入列名
                cell.setCellStyle(style);
                logger.info("createcolName :" + attr.name());
                continue;
            }

            if ("BOM类型".equals(attr.name())) {
                row.getSheet().setColumnWidth(col, Integer.parseInt(attr.colWidth()));
                cell = row.createCell(getExcelCol(attr.column()));// 创建列
                cell.setCellType(HSSFCell.CELL_TYPE_STRING);// 设置列中写入内容为String类型
                cell.setCellValue(attr.name());// 写入列名
                cell.setCellStyle(style);
                logger.info("createcolName :" + attr.name());
                continue;
            }
        }

    }

    @Override
    public void createRow(HSSFWorkbook wb, Object t, HSSFSheet sheet) {
        Drawing drawing = sheet.createDrawingPatriarch();
        HSSFCell cell;// 产生单元格
        if (flag) {
            row = ExcelTool.createRow(sheet);
        }
        row.setHeight((short) 2000);
        HSSFCellStyle style = wb.createCellStyle();
        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
        style.setFillBackgroundColor(HSSFColor.GREY_40_PERCENT.index);
        style.setAlignment(CellStyle.ALIGN_GENERAL);
        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        style.setWrapText(true);

        Field[] fields = t.getClass().getDeclaredFields();
        try {
            for (Field field : fields) {

                if (!field.isAccessible()) {
                    // 设置私有属性为可访问
                    field.setAccessible(true);
                }
                if (field.isAnnotationPresent(ExcelAttribute.class) && field.isAnnotationPresent(ExcelElement.class)) {
                    flag = false;
//					logger.debug("泛型：=====>" + getClass(field.getGenericType(), 0));
                    switch (ElementTypePath.getElementTypePath(field.getType().getTypeName())) {
                        case MAP:
                            ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class);
                            Map<?, ?> map = (Map<?, ?>) field.get(t);
                            if (map != null) {
                                StringBuffer strB = new StringBuffer();
                                for (Map.Entry<?, ?> entry : map.entrySet()) {
                                    strB.append(entry.getKey() + " : " + entry.getValue() + " , ");
                                }
                                if (strB.length() > 0) {
                                    strB.deleteCharAt(strB.length() - 1);
                                    strB.deleteCharAt(strB.length() - 1);
                                }

                                try {
                                    // 根据ExcelVOAttribute中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
                                    if (ea.isExport()) {
                                        cell = row.createCell(getExcelCol(ea.column()));// 创建cell
                                        cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                                        cell.setCellValue(strB == null ? "" : strB.toString());// 如果数据存在就填入,不存在填入空格.
                                        cell.setCellStyle(style);
                                    }
                                } catch (IllegalArgumentException e) {
                                    e.printStackTrace();
                                }
                            }
                            break;
                        default:
                            break;
                    }
                }
            }
            for (Field field : fields) {
                if (!field.isAccessible()) {
                    // 设置私有属性为可访问
                    field.setAccessible(true);
                }

                if (field.isAnnotationPresent(ExcelAttribute.class) && !field.isAnnotationPresent(ExcelElement.class)) {
                    ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class);
//					logger.debug("当前行:"+ea.column() + "====>value:" + field.get(t));
                    flag = true;
                    try {
                        //判断图片列，插入图片
                        if (ea.name().equals("图片")) {
                            //生成插入图片
                            String picUrl = field.get(t) == null ? "" : String.valueOf(field.get(t));

                            ByteArrayOutputStream byteArrayOut = new ByteArrayOutputStream();
                            BufferedImage bufferImg = null;
                            try {
                                bufferImg = ImageIO.read(new File(picUrl));


                                int width = bufferImg.getWidth();
                                int height = bufferImg.getHeight();

                                double a = width / height;

                                ImageIO.write(bufferImg, "jpg", byteArrayOut);
                                int pictureIdx = wb.addPicture(byteArrayOut.toByteArray(), HSSFWorkbook.PICTURE_TYPE_JPEG);
                                CreationHelper helper = sheet.getWorkbook().getCreationHelper();
                                ClientAnchor anchor = helper.createClientAnchor();

                                anchor.setCol1(getExcelCol(ea.column()));
                                anchor.setRow1(row.getRowNum());
                                // 获取单元格宽度和高度，单位都是像素
                               // int cellWidth = cell.getSheet().getColumnWidth(cell.getColumnIndex());
                               // short height1 = cell.getRow().getHeight();
                                // double cellWidth = sheet.getColumnWidthInPixels(cell.getColumnIndex());

                                cell = row.createCell(getExcelCol(ea.column()));
                                double cellHeight = cell.getRow().getHeightInPoints() / 72 * 96;// getHeightInPoints()方法获取的是点（磅），就是excel设置的行高，1英寸有72磅，一般显示屏一英寸是96个像素


                                double v = cellHeight/height;


                                // HSSFClientAnchor anchor = new HSSFClientAnchor(0, 0, 1023, 255,(short) getExcelCol(ea.column()), row.getRowNum(), (short)getExcelCol(ea.column()), row.getRowNum());
                                //注意：这个方法在新版本的POI中参数类型改成了（AnchorType anchorType）　
                                anchor.setAnchorType(3);

                                Picture picture = drawing.createPicture(anchor, pictureIdx);

                                picture.resize(v);
                                field.set(t, "");

                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }

                        // 根据ExcelVOAttribute中设置情况决定是否导出,有些情况需要保持为空,希望用户填写这一列.
                        if (ea.isExport()) {
                            cell = row.createCell(getExcelCol(ea.column()));// 创建cell
                            cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                            cell.setCellValue(field.get(t) == null ? "" : String.valueOf(field.get(t)));// 如果数据存在就填入,不存在填入空格.
                            cell.setCellStyle(style);

                        }
                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                } else if (field.isAnnotationPresent(ExcelElement.class)) {
                    flag = false;
//					logger.debug("泛型：=====>" + getClass(field.getGenericType(), 0));
                    switch (ElementTypePath.getElementTypePath(field.getType().getTypeName())) {
                        case SET:
                            Set<?> set = (Set<?>) field.get(t);
                            if (set != null) {
                                for (Object object : set) {
                                    createRow(wb, object, sheet);
                                }
                            }
                            break;
                        case LIST:
                            List<?> list = (List<?>) field.get(t);
                            if (list != null) {
                                for (Object object : list) {
                                    createRow(wb, object, sheet);
                                }
                            }
                            break;
                        case MAP:
                            break;
                        default:
                            createRow(wb, field.get(t), sheet);
                            break;
                    }
                }

            }
        } catch (SecurityException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        flag = true;
    }

    @Override
    public void createRowFlat(HSSFWorkbook wb, Object t, HSSFSheet sheet) {
        HSSFCell cell;// 产生单元格

        HSSFCellStyle style = wb.createCellStyle();
        style.setFillForegroundColor(HSSFColor.SKY_BLUE.index);
        style.setFillBackgroundColor(HSSFColor.GREY_40_PERCENT.index);
        style.setAlignment(CellStyle.ALIGN_GENERAL);
        style.setVerticalAlignment(CellStyle.VERTICAL_CENTER);
        style.setWrapText(true);

        Field[] fields = t.getClass().getDeclaredFields();
        try {

            for (Field field : fields) {
                if (!field.isAccessible()) {
                    // 设置私有属性为可访问
                    field.setAccessible(true);
                }

                if (field.isAnnotationPresent(ExcelAttribute.class) && !field.isAnnotationPresent(ExcelElement.class)) {
                    ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class);
//					logger.debug("当前行:"+ea.column() + "====>value:" + field.get(t));
                    flag = true;
                    try {
                        if (ea.name().equals("BOM名称")) {
                            //填充第一行 第二列单元格数据[0,1]
                            cell = sheet.getRow(0).createCell(1);
                            cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                            cell.setCellValue(field.get(t) == null ? "" : String.valueOf(field.get(t)));// 如果数据存在就填入,不存在填入空格.
                            cell.setCellStyle(style);
                        }

                        if (ea.name().equals("创建日期")) {
                            //填充第一行 第二列单元格数据[1,1]
                            cell = sheet.getRow(1).createCell(1);
                            cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                            cell.setCellValue(field.get(t) == null ? "" : String.valueOf(field.get(t)));// 如果数据存在就填入,不存在填入空格.
                            cell.setCellStyle(style);
                        }

                        if (ea.name().equals("创建人")) {
                            //填充第一行 第二列单元格数据[1,1]
                            cell = sheet.getRow(1).createCell(3);
                            cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                            cell.setCellValue(field.get(t) == null ? "" : String.valueOf(field.get(t)));// 如果数据存在就填入,不存在填入空格.
                            cell.setCellStyle(style);
                        }

                        if (ea.name().equals("BOM类型")) {
                            //填充第一行 第二列单元格数据[1,1]
                            cell = sheet.getRow(1).createCell(5);
                            cell.setCellType(HSSFCell.CELL_TYPE_STRING);
                            cell.setCellValue(field.get(t) == null ? "" : String.valueOf(field.get(t)));// 如果数据存在就填入,不存在填入空格.
                            cell.setCellStyle(style);
                        }

                    } catch (IllegalArgumentException e) {
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        e.printStackTrace();
                    }
                }

            }
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }


    @Override
    public List<T> dispatch(Sheet sheet) {
        Map<String, PictureData> pictures = null;
        if (sheet instanceof HSSFSheet) {
            pictures = ExcelUtils.getPictures((HSSFSheet) sheet);
        } else if (sheet instanceof XSSFSheet) {
            pictures = ExcelUtils.getPictures((XSSFSheet) sheet);
        }

        int rows = sheet.getPhysicalNumberOfRows();
        List<Integer> idCols = getIdCols(clazz, null);

        List<Class<?>> clazzs = getAllClass(clazz, null);
        Map<String, String> tuples = getTuple(sheet, rows);
        if (idCols.size() != clazzs.size()) {
            logger.error("class 数目不一致");
            return null;
        }
        Map<String, Map<String, Object>> instanceMap = null;
        int size = idCols.size();
        for (int i = size - 1; i > -1; i--) {
            //默认起始行为1
            for (int j = 1; j < rows; j++) {
                int row = j;
                int childIdCol = -1;
                int idCol = idCols.get(i);
                int parentIdCol = -1;
                if (i > 0) {
                    parentIdCol = idCols.get(i - 1);
                }
                if (i < size - 1) {
                    childIdCol = idCols.get(i + 1);
                }
                //logger.debug(clazzs.get(i) + "===" + row + "====" + idCol + "======" + parentIdCol);
                instanceMap = createInstance(clazzs.get(i), row, idCol, parentIdCol, childIdCol, tuples, instanceMap, pictures);
            }

        }
        List<T> list = new ArrayList<T>();
        Map<String, Object> map = instanceMap.get(idCols.get(0) + "");
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            list.add((T) entry.getValue());
        }
        return list;
    }

    /**
     * 合并数据
     */
    public int mergedRegio(Object t, HSSFSheet sheet, int rowStart) {
        //获取子节点的数目
        Field[] fields = t.getClass().getDeclaredFields();
        int rowEnd = rowStart + childNodes(t, 0) - 1;
        for (Field field : fields) {
            if (field.isAnnotationPresent(ExcelAttribute.class)) {
                ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class);
                CellRangeAddress cellRangeAddress = new CellRangeAddress(rowStart, rowEnd, getExcelCol(ea.column()), getExcelCol(ea.column()));
                sheet.addMergedRegion(cellRangeAddress);
            } else if (field.isAnnotationPresent(ExcelElement.class) && !field.isAnnotationPresent(ExcelAttribute.class)) {
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }
                int childRowStart = rowStart;
                try {
                    switch (ElementTypePath.getElementTypePath(field.getType().getName())) {
                        case SET:
                            Set<?> set = (Set<?>) field.get(t);
                            if (set != null) {
                                for (Object object : set) {
                                    childRowStart = mergedRegio(object, sheet, childRowStart);
                                }
                            }
                            break;
                        case LIST:
                            List<?> list = (List<?>) field.get(t);
                            if (list != null) {
                                for (Object object : list) {
                                    childRowStart = mergedRegio(object, sheet, childRowStart);
                                }
                            }
                            break;
                        case MAP:
                            break;
                        default:
                            childRowStart = mergedRegio(field.get(t), sheet, childRowStart);
                            break;
                    }
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        return rowEnd + 1;

    }

    /**
     * 统计子节点的叶子数目
     *
     * @param t
     * @param childNodeNum
     * @return int 子节点的数目
     * @throws
     * @Description: TODO(一个类只支持包含一个集合)
     */
    private int childNodes(Object t, int childNodeNum) {
        Field[] fields = t.getClass().getDeclaredFields();
        boolean childNodeFlag = true;
        for (Field field : fields) {
            if (field.isAnnotationPresent(ExcelElement.class) && !field.isAnnotationPresent(ExcelAttribute.class)) {
                if (!field.isAccessible()) {
                    field.setAccessible(true);
                }
                childNodeFlag = false;
                try {
                    switch (ElementTypePath.getElementTypePath(field.getType().getName())) {
                        case SET:
                            Set<?> set = (Set<?>) field.get(t);
                            if (set != null) {
                                if (set.size() == 0) {
                                    childNodeFlag = true;
                                } else {
                                    for (Object object : set) {
                                        childNodeNum = childNodes(object, childNodeNum);
                                    }
                                }

                            } else {
                                childNodeFlag = true;
                            }
                            break;
                        case LIST:
                            List<?> list = (List<?>) field.get(t);
                            if (list != null) {
                                if (list.size() == 0) {
                                    childNodeFlag = true;
                                } else {
                                    for (Object object : list) {
                                        childNodeNum = childNodes(object, childNodeNum);
                                    }
                                }
                            } else {
                                childNodeFlag = true;
                            }
                            break;
                        case MAP:
                            break;
                        default:
                            childNodeNum = childNodes(field.get(t), childNodeNum);
                            break;
                    }
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

            }
        }
        if (childNodeFlag) {
            childNodeNum++;
        }
        return childNodeNum;
    }

    /**
     * 创建实例对象 并装配关系
     *
     * @param clazz       当前实例对象的类
     * @param row         当前实例对象的行
     * @param idCol       当前实例对象的id列
     * @param parentIdCol 父实例对象的id列
     * @param tuples      存放所有的值
     * @param instanceMap 装配后的对象
     * @throws
     */
    @SuppressWarnings("unchecked")
    private Map<String, Map<String, Object>> createInstance(Class<?> clazz, int row, int idCol, int parentIdCol, int childIdCol, Map<String, String> tuples, Map<String, Map<String, Object>> instanceMap, Map<String, PictureData> pictures) {

        // TODO判断 是否存在该实例
        if (instanceMap == null) {
            instanceMap = new HashMap<>();
        }
        if (!tuples.containsKey(row + "," + idCol)) {
            return instanceMap;
        }

        Object entity = null;
        try {
            entity = clazz.newInstance();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        }
        //同一类对象的map 以 id_parentId作为键
        Map<String, Object> colMap;
        if (instanceMap.containsKey(idCol + "")) {
            colMap = instanceMap.get(idCol + "");
        } else {
            colMap = new HashMap<>();
            instanceMap.put(idCol + "", colMap);
        }
        //判断是否有父级对象
        String id = tuples.get(row + "," + idCol);
        ;
        if (parentIdCol > -1) {
            String parentId = tuples.get(row + "," + parentIdCol);
            colMap.put(parentId + "_" + id, entity);

        } else {
            colMap.put(id, entity);
        }
//		logger.debug("colMap===========>"+colMap.size());
        Field[] fields = clazz.getDeclaredFields();


        for (Field field : fields) {
            if (!field.isAccessible()) {
                field.setAccessible(true);
            }

            //判断属性是否有rowNum 如果有 则设值
            if (field.getName().equals("rowNum")) {
                try {

                    field.set(entity, row);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

            //判断图片列是否为空，如果有图片列，强制赋值
            if (pictures.size() > 0 && field.getName().equals("picObj")) {
                PictureData hssfPictureData = pictures.entrySet().stream().map(item -> {
                    String pickey = item.getKey().split("-")[0];
                    if (pickey.equals(String.valueOf(row))) {
                        return item.getValue();
                    }
                    return null;
                }).filter(f -> f != null).findFirst().orElseGet(() -> null);
                try {
                    field.set(entity, hssfPictureData);
                } catch (IllegalAccessException e) {
                    e.printStackTrace();
                }
            }

            //对普通属性进行设值
            if (field.isAnnotationPresent(ExcelAttribute.class) && !field.isAnnotationPresent(ExcelElement.class)) {
                ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class);
                String value = tuples.get(row + "," + getExcelCol(ea.column()));
                Class<?> fieldType = field.getType();
                try {
                    if (String.class == fieldType) {
                        field.set(entity, String.valueOf(value));
                    } else if ((Integer.TYPE == fieldType) || (Integer.class == fieldType)) {
                        field.set(entity, Integer.parseInt(value));
                    } else if ((Long.TYPE == fieldType) || (Long.class == fieldType)) {
                        field.set(entity, Long.valueOf(value));
                    } else if ((Float.TYPE == fieldType) || (Float.class == fieldType)) {
                        field.set(entity, Float.valueOf(value));
                    } else if ((Short.TYPE == fieldType) || (Short.class == fieldType)) {
                        field.set(entity, Short.valueOf(value));
                    } else if ((Double.TYPE == fieldType) || (Double.class == fieldType)) {
                        field.set(entity, Double.valueOf(value));
                    } else if (Character.TYPE == fieldType) {
                        if ((value != null) && (value.length() > 0)) {
                            field.set(entity, Character.valueOf(value.charAt(0)));
                        }
                    }
                } catch (NumberFormatException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            } else if (field.isAnnotationPresent(ExcelElement.class)) {
                Map<String, Object> map = instanceMap.get(childIdCol + "");
                List<Object> entitys = new ArrayList<>();
                if (map != null) {
                    for (Map.Entry<String, Object> entry : map.entrySet()) {
                        String key = entry.getKey();
                        if (key.indexOf("_") > -1) {
                            String[] str = key.split("_");
                            String childParentId = str[0];
                            if (childParentId.equals(id)) {
                                entitys.add(entry.getValue());
                            }
                        }
                    }
                }

                String typeName = field.getType().getName();
                try {
                    switch (ElementTypePath.getElementTypePath(typeName)) {
                        case SET:
                            Set<Object> set = (Set<Object>) field.get(entity);
                            if (set == null) {
                                set = new HashSet<>();
                                field.set(entity, set);
                            }
                            for (Object object : entitys) {
                                set.add(object);
                            }
                            break;
                        case LIST:
                            List<Object> list = (List<Object>) field.get(entity);
                            if (list == null) {
                                list = entitys;
                                field.set(entity, list);
                            } else {
                                for (Object object : entitys) {
                                    list.add(object);
                                }
                            }
                            break;
                        case MAP:
                            if (field.isAnnotationPresent(ExcelAttribute.class)) {
                                if (getClass(field.getGenericType(), 0).getName().equals("java.lang.String")) {
                                    Map<String, String> imap = (Map<String, String>) field.get(entity);
                                    if (imap == null) {
                                        imap = new HashMap<>();
                                        field.set(entity, imap);
                                    }
                                    ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class);
                                    String value = tuples.get(row + "," + getExcelCol(ea.column()));
                                    if (value.indexOf(",") > -1) {
                                        String[] str = value.split(",");
                                        for (String string : str) {
                                            if (string.indexOf(":") > -1) {
                                                String[] keyAndVlaue = string.split(":");
                                                if (keyAndVlaue.length == 2) {
                                                    imap.put(keyAndVlaue[0].trim(), keyAndVlaue[1].trim());
                                                }
                                            }
                                        }
                                    }
                                }


                            }
                            break;
                        default:
                            if (entitys.size() == 1) {
                                field.set(entity, entitys.get(0));
                            }
                            break;

                    }
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
            }
        }
        return instanceMap;
    }


    /**
     * 获取所有标识列（用来获取父级id）
     *
     * @param clazz
     * @param idCols
     * @return List<Integer> 返回类型
     * @throws
     */
    private List<Integer> getIdCols(Class<?> clazz, List<Integer> idCols) {
        if (idCols == null) {
            idCols = new ArrayList<>();
        }
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(ExcelID.class) && field.isAnnotationPresent(ExcelAttribute.class)) {
                ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class);
                idCols.add(getExcelCol(ea.column()));
            }
        }
        for (Field field : fields) {
            //TODO 此处集合需要做判断
            if (field.isAnnotationPresent(ExcelElement.class)) {
                clazz = getClass(field.getGenericType(), 0);
//				logger.debug(clazz);
                getIdCols(clazz, idCols);
            }
        }
        return idCols;
    }

    private List<Class<?>> getAllClass(Class<?> clazz, List<Class<?>> clazzs) {
        if (clazzs == null) {
            clazzs = new ArrayList<>();
        }
        clazzs.add(clazz);
        Field[] fields = clazz.getDeclaredFields();
        for (Field field : fields) {
            //TODO 此处集合需要做判断
            if (field.isAnnotationPresent(ExcelElement.class) && !field.isAnnotationPresent(ExcelAttribute.class)) {
                clazz = getClass(field.getGenericType(), 0);
                getAllClass(clazz, clazzs);
            }
        }
        return clazzs;
    }


    /**
     * 获取 excel中的数据 元组
     *
     * @param sheet
     * @return List<List < String>> excel元组
     * @throws
     */
    private Map<String, String> getTuple(Sheet sheet, int rows) {

        Map<String, String> tuples = new HashMap<>();
        //获取列
        List<Field> fields = getAllField(clazz, null);
        // 从第2行开始取数据,默认第一行是表头.
        for (int i = 1; i < rows; i++) {
            for (Field field : fields) {
                if (field.isAnnotationPresent(ExcelAttribute.class)) {
                    ExcelAttribute ea = field.getAnnotation(ExcelAttribute.class);
                    int col = getExcelCol(ea.column());
                    String key = i + "," + col;
                    //  logger.info("key:"+key);
                    if (ExcelTool.isMergedRegion(sheet, i, col)) {
                        // 以(行,列）作为一个元组
                        String value = ExcelTool.getMergedRegionValue(sheet, i, col);
                        tuples.put(key, value);
                    } else {
                        Row fRow = sheet.getRow(i);
                        Cell fCell = fRow.getCell(col);
                        String value = ExcelTool.getCellValue(fCell).trim();
                        tuples.put(key, value);
                    }
                }
            }
        }
        return tuples;
    }

    /**
     * 获取图片和位置 (xls)
     *
     * @param sheet
     * @return
     * @throws IOException
     */
    public static Map<String, PictureData> getPictures(HSSFSheet sheet) {
        Map<String, PictureData> map = new HashMap<>();
        List<HSSFShape> list = sheet.getDrawingPatriarch().getChildren();
        for (HSSFShape shape : list) {
            if (shape instanceof HSSFPicture) {
                HSSFPicture picture = (HSSFPicture) shape;
                HSSFClientAnchor cAnchor = (HSSFClientAnchor) picture.getAnchor();
                HSSFPictureData pdata = picture.getPictureData();
                String key = cAnchor.getRow1() + "-" + cAnchor.getCol1(); // 行号-列号
                map.put(key, pdata);
            }
        }
        return map;
    }

    /**
     * 获取图片和位置 (xlsx)
     *
     * @param sheet
     * @return
     * @throws IOException
     */
    public static Map<String, PictureData> getPictures(XSSFSheet sheet) {
        Map<String, PictureData> map = new HashMap<>();
        List<POIXMLDocumentPart> list = sheet.getRelations();
        for (POIXMLDocumentPart part : list) {
            if (part instanceof XSSFDrawing) {
                XSSFDrawing drawing = (XSSFDrawing) part;
                List<XSSFShape> shapes = drawing.getShapes();
                for (XSSFShape shape : shapes) {
                    XSSFPicture picture = (XSSFPicture) shape;
                    XSSFClientAnchor anchor = picture.getPreferredSize();
                    CTMarker marker = anchor.getFrom();
                    String key = marker.getRow() + "-" + marker.getCol();
                    map.put(key, picture.getPictureData());
                }
            }
        }
        return map;
    }
}


