package com.cftech.core.util;

import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.ss.usermodel.*;
import org.dom4j.Document;
import org.dom4j.Element;
import org.dom4j.Node;
import org.dom4j.io.SAXReader;

import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.*;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author 作者 lisw:
 * @version 创建时间：2016年11月22日 下午7:28:46 类说明
 */
public class ExcelUtils {
	public static String[] objListToExcel(HttpServletResponse response,
			String name, Map data) {
		Map<String, String> filedData = (Map<String, String>) data.get("filed");
		List listData = (List) data.get("listData");
		Object[] keys = filedData.keySet().toArray();
		String[] ziDuanKeys = new String[keys.length];
		for (int k = 0; k < keys.length; k++) {
			String temp = keys[k].toString();
			int xuHao = Integer.valueOf(temp.split("-")[0]);
			ziDuanKeys[xuHao] = temp.split("-")[1];
		}
		try {
			String path = name + ".xls";
			HSSFWorkbook wb = new HSSFWorkbook();
			HSSFSheet sheet = wb.createSheet();
			for (int i = 0; i < listData.size(); i++) {
				HSSFRow row = sheet.createRow(i);
				Object obj = listData.get(i);
				for (int j = 0; j < ziDuanKeys.length; j++) {
					HSSFCell cell = row.createCell(j);
					if (i == 0) {
						sheet.setColumnWidth(j, 6000);
						cell.setCellValue(new HSSFRichTextString(filedData
								.get(j +"-"+ ziDuanKeys[j])));
					} else {
						String ziDuanName = (String) ziDuanKeys[j];
						System.out.println(ziDuanName);
						ziDuanName = ziDuanName.replaceFirst(ziDuanName
								.substring(0, 1), ziDuanName.substring(0, 1)
								.toUpperCase());
						ziDuanName = "get" + ziDuanName;
						Class clazz = Class.forName(obj.getClass().getName());
						Method[] methods = clazz.getMethods();
						Pattern pattern = Pattern.compile(ziDuanName);
						Matcher mat = null;
						for (Method m : methods) {
							mat = pattern.matcher(m.getName());
							if (mat.find()) {
								Object shuXing = m.invoke(obj, null);
								String value="";
								if (shuXing != null) {
									value=shuXing.toString();
									if(ziDuanName.equals("getSource")){
										if(value.equals("1")){
											value="新品推荐";
										}else if(value.equals("2")){
											value="附近门店";
										}else{
											value="设计案例";
										}
										cell.setCellValue(value);// 这里可以做数据格式处理
									}else if(ziDuanName.equals("getDelflag")){
										if(value.equals("0")){
											value="收藏";
										}else{
											value="取消收藏";
										}
										cell.setCellValue(value);// 这里可以做数据格式处理
									}else{
										cell.setCellValue(shuXing.toString());// 这里可以做数据格式处理
									}
								} else {
									cell.setCellValue(value);
								}
								break;
							}
						}
					}
				}
			}
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			try {
				wb.write(os);
			} catch (IOException e) {
				e.printStackTrace();
			}
			byte[] content = os.toByteArray();
			InputStream is = new ByteArrayInputStream(content);
			// 设置response参数，可以打开下载页面
			response.reset();
			response.setContentType("application/vnd.ms-excel;charset=utf-8");
			response.setHeader("Content-Disposition", "attachment;filename="
					+ new String((name + ".xls").getBytes(), "iso-8859-1"));
			ServletOutputStream out = response.getOutputStream();
			BufferedInputStream bis = null;
			BufferedOutputStream bos = null;
			try {
				bis = new BufferedInputStream(is);
				bos = new BufferedOutputStream(out);
				byte[] buff = new byte[2048];
				int bytesRead;
				// Simple read/write loop.
				while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
					bos.write(buff, 0, bytesRead);
				}
			} catch (final IOException e) {
				throw e;
			} finally {
				if (bis != null)
					bis.close();
				if (bos != null)
					bos.close();
			}
			return null;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}
	/**
	 * 导出表格
	 * name:导出表格的名称
	 * listObject:数据集合
	 * mappingName:配置的映射名称
	 * */
	public static Boolean export(HttpServletRequest request,HttpServletResponse response,String name, List listObject,String mappingName) throws Exception{
		List<Map<String,Object>> listData = ExcelUtils.convertBeans(listObject);
		List<Map<String,Object>> titles=ExcelUtils.analysisExportTitle(mappingName,request);
		try {
			String path = name + ".xls";
			HSSFWorkbook wb = new HSSFWorkbook();
			HSSFSheet sheet = wb.createSheet();
			for (int i = 0; i <= listData.size(); i++) {
				//创建一行
				HSSFRow row = sheet.createRow(i);
				//获取此行的数据
				Map<String,Object> rowDate=null;
				if(i>0){
					rowDate = (Map<String, Object>) listData.get(i-1);
				}else{
					try {
						rowDate = (Map<String, Object>) listData.get(i);
					} catch (Exception e) {
						// TODO: handle exception
					}
				}
				for (int j = 0; j < titles.size(); j++) {
					//创建单元格
					HSSFCell cell = row.createCell(j);
					//获取此列的标题
					String title = titles.get(j).get("titleName").toString();
					//获取此列的属性名称
					String columnName = titles.get(j).get("attrName").toString();
					//获取此列的数据转化类型
					Map<String,Object> formatDate = (Map<String, Object>) titles.get(j).get("formats");
					//获取此列的数据是否需要date转型
					String dateformatDate = (String) titles.get(j).get("formatdate");
					Object value=null;
					if(rowDate!=null){
						if(StringUtils.isNoneBlank(dateformatDate)){
							value=rowDate.get(columnName);
						}else{
							//获取此单元格的数据
							value="";
							if(rowDate.get(columnName)!=null){
								value= rowDate.get(columnName).toString();
							}
						}
					}
					if (i == 0) {
						//创建标题行
						sheet.setColumnWidth(j, 6000);
						cell.setCellValue(new HSSFRichTextString(title));
						CellStyle cellStyle = wb.createCellStyle();
						Font font = wb.createFont();
						cellStyle.setFillForegroundColor((short) 12);
						cellStyle.setFillPattern(FillPatternType.SOLID_FOREGROUND);// 填充模式
						cellStyle.setBorderTop(BorderStyle.THIN);// 上边框为细边框
						cellStyle.setBorderRight(BorderStyle.THIN);// 右边框为细边框
						cellStyle.setBorderBottom(BorderStyle.THIN);// 下边框为细边框
						cellStyle.setBorderLeft(BorderStyle.THIN);// 左边框为细边框
						cellStyle.setAlignment(HorizontalAlignment.LEFT);// 对齐
						cellStyle.setFillForegroundColor(HSSFColor.GREEN.index);
						cellStyle.setFillBackgroundColor(HSSFColor.GREEN.index);
						//font.setBoldweight(Font.BOLDWEIGHT_NORMAL);
						font.setBold(true);
						font.setFontHeightInPoints((short) 14);//字体大小
						font.setColor(HSSFColor.WHITE.index);
						// 应用标题字体到标题样式
						cellStyle.setFont(font);
						cell.setCellStyle(cellStyle);
					} else {
						// 判断数据所对应的转型数据
						if(formatDate !=null && formatDate.get(value)!=null){
							//此列数据需要转型
							cell.setCellValue(formatDate.get(value).toString());
						}else{
							if(value!=null){
								cell.setCellValue(value.toString());
							}
						}
						if(StringUtils.isNoneBlank(dateformatDate)){
							if(value!=null){
								if(value instanceof Date){
									Date date=(Date) value;
									String formatdate=new SimpleDateFormat(dateformatDate).format(date);
									cell.setCellValue(formatdate);
								}else if (value instanceof String){
									if(StringUtils.isNotBlank(value.toString())){
										Date date=new Date();
										date.setTime(Long.valueOf(value.toString()));
										String formatdate=new SimpleDateFormat(dateformatDate).format(date);
										cell.setCellValue(formatdate);
									}else{
										cell.setCellValue(value.toString());
									}
								}else{
									cell.setCellValue(value.toString());
								}
							}
						}

					}
				}
			}
			ByteArrayOutputStream os = new ByteArrayOutputStream();
			try {
				wb.write(os);
			} catch (IOException e) {
				e.printStackTrace();
			}
			byte[] content = os.toByteArray();
			InputStream is = new ByteArrayInputStream(content);
			// 设置response参数，可以打开下载页面
			response.reset();
			response.setContentType("application/vnd.ms-excel;charset=utf-8");
			response.setHeader("Content-Disposition", "attachment;filename="
					+ new String((path).getBytes(), "iso-8859-1"));
			ServletOutputStream out = response.getOutputStream();
			BufferedInputStream bis = null;
			BufferedOutputStream bos = null;
			try {
				bis = new BufferedInputStream(is);
				bos = new BufferedOutputStream(out);
				byte[] buff = new byte[2048];
				int bytesRead;
				// Simple read/write loop.
				while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
					bos.write(buff, 0, bytesRead);
				}
			} catch (final IOException e) {
				throw e;
			} finally {
				if (bis != null)
					bis.close();
				if (bos != null)
					bos.close();
			}
		} catch (Exception e) {
			e.printStackTrace();
			return false;
		}
		return true;
	}
	/**
     * 将一个 JavaBean 对象转化为一个  Map
     * @param bean 要转化的JavaBean 对象
     * @return 转化出来的  Map 对象
     * @throws IntrospectionException 如果分析类属性失败
     * @throws IllegalAccessException 如果实例化 JavaBean 失败
     * @throws InvocationTargetException 如果调用属性的 setter 方法失败
     */
    public static Map<String,Object> convertBean(Object bean)
            throws IntrospectionException, IllegalAccessException, InvocationTargetException {
        Class<? extends Object> type = bean.getClass();
        Map<String,Object> returnMap = new HashMap<String,Object>();
        BeanInfo beanInfo = Introspector.getBeanInfo(type);
        PropertyDescriptor[] propertyDescriptors =  beanInfo.getPropertyDescriptors();
        for (int i = 0; i< propertyDescriptors.length; i++) {
            PropertyDescriptor descriptor = propertyDescriptors[i];
            String propertyName = descriptor.getName();
            if (!propertyName.equals("class")) {
                Method readMethod = descriptor.getReadMethod();
                Object result = readMethod.invoke(bean, new Object[0]);
                if (result != null) {
                    returnMap.put(propertyName, result);
                } else {
                    returnMap.put(propertyName, "");
                }
            }
        }
        return returnMap;
    }
    /**
     * 转化List<Object>为List<Map<String,Object>>
     * */
    public static List<Map<String,Object>>  convertBeans(List beans) throws IllegalAccessException, InvocationTargetException, IntrospectionException {
    	List<Map<String,Object>> result = new ArrayList<Map<String,Object>>();
    	for (Object object : beans) {
    		if(object instanceof Map){
    			result.add((Map<String, Object>) object);
    		}else{
    			result.add(convertBean(object));
    		}
		}
        return result;
    }

    /**
     *解析配置的导出格式
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static List<Map<String, Object>> analysisExportTitle(String tableName,HttpServletRequest request) throws Exception {
    	//定义一个最终要解析成功的数据集合
    	List<Map<String,Object>> titles = new ArrayList<Map<String,Object>>();
        SAXReader saxReader = new SAXReader();
        String webpath=request.getSession().getServletContext().getRealPath("/");
        File inputFile = new File(webpath+"/WEB-INF/classes/ExportMapper.xml");
        Document document = saxReader.read(inputFile);
        Element root = document.getRootElement();
        List cdList = root.selectNodes("/ROOT/"+tableName+"/titles/title");
        for (Object object : cdList) {
        	Element ele = (Element) object;
        	Node attrName=ele.selectSingleNode("./attrName");
        	Node titleName=ele.selectSingleNode("./titleName");
        	Node formats=ele.selectSingleNode("./formats");
        	Node formatdate=ele.selectSingleNode("./formatdate");
        	if(attrName!=null && titleName!=null){
        		Map<String,Object> map = new HashMap<String, Object>();
        		map.put("attrName", attrName.getText());
        		map.put("titleName", titleName.getText());
        		//判断是否要做数据转化
        		if(formats != null){
        			Map<String, Object> allFormats=new HashMap<String, Object>();
        			List allFormatElement=formats.selectNodes("./format");
        			for (Object object2 : allFormatElement) {
        				Element format = (Element) object2;
        				String tempFormatKey=format.selectSingleNode("./key").getText();
        				String tempFormatValue=format.selectSingleNode("./value").getText();
        				allFormats.put(tempFormatKey, tempFormatValue);
					}
        			map.put("formats",allFormats);
        		}
        		//是否是日期转型
        		if(formatdate !=null){
        			map.put("formatdate", formatdate.getText());
        		}
        		titles.add(map);
        	}
		}
        return titles;
    }
}

