package com.engine.kq.wfset.attendance.framework;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.text.DateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFCellStyle;
import org.apache.poi.hssf.usermodel.HSSFDataFormat;
import org.apache.poi.hssf.usermodel.HSSFDateUtil;
import org.apache.poi.hssf.usermodel.HSSFFont;
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.hssf.util.HSSFColor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;
import org.json.JSONObject;
import weaver.common.DateUtil;
import weaver.common.FileUtil;
import weaver.common.StringUtil;
import weaver.file.MyMultiPartHelper;
import weaver.general.BaseBean;
import weaver.hrm.common.SplitPageTagFormat;

/**
 * 
 * @author wcd
 * @version 1.0 2014-11-18
 */
public class BaseController<T> extends BaseBean {
	private BaseManager<T> manager;

	private String separator;

	private String rootPath;

	private String appresPath;

	private Hashtable multiData;

	private static final int B = 8 * 1024;

	private static final String SUFFIX = ".xls";

	private static final String ENCODING = "UTF-8";

	protected SplitPageTagFormat format;

	public BaseController() {
		this.separator = File.separator;
		this.multiData = new Hashtable();
		this.rootPath = weaver.general.GCONST.getRootPath();
		this.appresPath = this.rootPath + "appres" + separator;
		this.format = new SplitPageTagFormat();
	}

	public BaseManager<T> getManager() {
		return manager;
	}

	public void setManager(BaseManager<T> manager) {
		this.manager = manager;
	}
	
	public String getRootPath() {
		return rootPath;
	}

	public String getAppresPath() {
		return appresPath;
	}
	
	public JSONObject handle(HttpServletRequest request, HttpServletResponse response) throws Exception {
		String filePath = StringUtil.getURLDecode(request.getParameter("thumbnailFilePath"));
		if(StringUtil.isNotNull(filePath)) {
			if(!filePath.startsWith("http")) {
				filePath = (filePath.startsWith("/") ? "" : "/") + filePath.replaceAll("\\\\","/");
			}
			response.sendRedirect(filePath);
		}
		return new JSONObject();
	}
	
	protected void upload(HttpServletRequest request, HttpServletResponse response, String filePath) throws IOException {
		this.multiData = getMultiData(request);
		File file = uploadFile(filePath);
		if(file != null && file.isFile()) {
			this.readFile(file);
			this.delFile(file);
		}
		this.closeWindow(response);
	}
	
	private Hashtable getMultiData(HttpServletRequest request) {
		Hashtable result = null; 
		int contentLength = request.getContentLength();
		String contentType = StringUtil.vString(request.getContentType());
		if(contentType.toLowerCase().startsWith("multipart/form-data")) {
			MyMultiPartHelper multiHelper = new MyMultiPartHelper();
			String boundary = "--" + multiHelper.getBoundary(contentType);
			try {result = multiHelper.parseMultiPart(request.getInputStream(), boundary, contentLength);} catch (Exception e) {}
		}
		return result;
	}
	
	private File uploadFile(String filePath) {
		Hashtable attachment = multiData == null ? null : (Hashtable)multiData.get("filePath");
		File tempFile = null;
		if(attachment != null) {
			if(StringUtil.isNotNull((String)attachment.get("filename"))) {
			    filePath = this.appresPath + filePath + separator + "upload" + separator;
			    FileUtil.mkDir(filePath) ;
			    tempFile = new File(filePath + java.util.UUID.randomUUID().getMostSignificantBits() + SUFFIX);
			    
			    FileOutputStream out = null;
			    ByteArrayInputStream in = null;
				Object content = attachment.get("content") ;
				try {
					in = (content instanceof String) ? new ByteArrayInputStream(((String)content).getBytes("ISO-8859-1")) : (ByteArrayInputStream)content;
				} catch (Exception e) {
					in = (content instanceof String) ? new ByteArrayInputStream(((String)content).getBytes()) : (ByteArrayInputStream)content;
				}
			    try {
			    	out = new FileOutputStream(tempFile);
			        byte temp[] = new byte[B];
			        int count = 0;
			        while ((count = in.read(temp)) > 0) out.write(temp, 0, count);
			    } catch(Exception e) {
					writeLog(e);
				} finally {
					IOUtils.closeQuietly(in);
					IOUtils.closeQuietly(out);
			    }
			}
		}
		return tempFile;
	}
	
	private void readFile(File file) {
		InputStream in = null;
		try {
			in = new FileInputStream(file);
			HSSFWorkbook wb = new HSSFWorkbook(new POIFSFileSystem(in));
			HSSFSheet sheet = wb.getSheetAt(0);
			HSSFRow row = null;
			for (int i = 0; i < sheet.getLastRowNum(); i++) {
				row = sheet.getRow(i+1);
				saveBean(row);
			}
		} catch (Exception e) {
			writeLog(e);
		} finally {
			IOUtils.closeQuietly((FileInputStream)in);
	    }
	}
	
	private void delFile (final File file) {
		new Thread(new Runnable() {
			public void run() {
				try {
					Thread.sleep(100);
					file.delete();
				} catch (InterruptedException e) {
				}
			}
		}).start();
	}
	
	protected String getCellValue(HSSFCell cell) {
		String cellValue = "";
		switch (cell.getCellType()) {
		case NUMERIC:
			if (HSSFDateUtil.isCellDateFormatted(cell)) {
				Date date = cell.getDateCellValue();
				if (cell.getCellStyle().getDataFormat() == HSSFDataFormat.getBuiltinFormat("h:mm:ss")) {
					cellValue = DateUtil.getDate(date, "HH:mm:ss");
				} else {
					cellValue = DateUtil.getDate(date);
				}
			} else {
				cellValue = StringUtil.vString(cell.getNumericCellValue());
			}
			break;
		case STRING:
			cellValue = StringUtil.vString(cell.getStringCellValue());
			break;
		case FORMULA:
			cellValue = StringUtil.vString(DateFormat.getDateInstance().format((cell.getDateCellValue())));
			break;
		}
		return cellValue;
	}

	protected void download(HttpServletRequest request, HttpServletResponse response, String filePath, String fileName, String downName) {
		if(request == null || response == null || StringUtil.isNull(filePath) || StringUtil.isNull(fileName)) return;
		filePath = this.appresPath + filePath + separator + "download" + separator;
		fileName = fileName.endsWith(SUFFIX) ? fileName : (fileName + SUFFIX);
		downName = downName.endsWith(SUFFIX) ? downName : (downName + SUFFIX);
		
		File file = new File(filePath + fileName);
		if(!file.isFile()) return;
		
		InputStream in = null;
		ServletOutputStream out = null;
		try {
			in = new FileInputStream(file);
			out = response.getOutputStream();
			initOut(request, response, downName);
			response.setContentLength((int)file.length());
			
			int count = 0;
			byte[] temp = new byte[B];
			while ((count = in.read(temp)) >= 0) out.write(temp, 0, count);
			out.flush();
		} catch(Exception e) {
			writeLog(e);
		} finally {
			IOUtils.closeQuietly((FileInputStream)in);
			IOUtils.closeQuietly(out);
	    }
	}
	
	private HSSFCellStyle createStyle(HSSFWorkbook wb, int type) {
		HSSFCellStyle style = wb.createCellStyle();
		style.setVerticalAlignment(VerticalAlignment.CENTER);
		style.setAlignment(HorizontalAlignment.CENTER);
		style.setWrapText(true);
		style.setBorderTop(BorderStyle.THIN);
		style.setBorderRight(BorderStyle.THIN);
		style.setBorderBottom(BorderStyle.THIN);
		style.setBorderLeft(BorderStyle.THIN);
		
		HSSFFont font = null;
		switch(type) {
		case 0:
			font = wb.createFont(); 
			font.setBold(true);
			font.setFontHeightInPoints((short) 15); 
			style.setAlignment(HorizontalAlignment.CENTER);
			style.setFont(font);
			break;
		case 1:
			font = wb.createFont(); 
			font.setBold(true);
			style.setFillPattern( FillPatternType.SOLID_FOREGROUND);
			style.setFillForegroundColor(IndexedColors.GREY_25_PERCENT.index);
			style.setFillBackgroundColor(IndexedColors.WHITE.index);
			style.setAlignment(HorizontalAlignment.CENTER);
			style.setFont(font);
			break;
		case 2:
			style.setAlignment(HorizontalAlignment.CENTER);
			break;
		}
		return style;
	}
	
	private HSSFRow createEmptyRow(HSSFSheet sheet, int rowIndex, int cLength) {
		HSSFRow row = sheet.createRow(rowIndex);
		HSSFCell ce = null;
		for(int i=0; i<cLength; i++){
			ce = row.createCell((short)i);
			ce.setCellType(CellType.STRING);
			ce.setCellValue("");
		}
		return row;
	}
	
	private HSSFRow createTitleRow(HSSFSheet sheet, int rowIndex, int cLength, HSSFCellStyle tStyle, String title) {
		HSSFRow row = sheet.createRow(rowIndex);
		HSSFCell ce = null;
		for(int i=0; i<cLength; i++){
			ce = row.createCell((short)i);
			ce.setCellStyle(tStyle);
			ce.setCellType(CellType.STRING);
			ce.setCellValue(i == 0 ? title : "");
		}
		row = createEmptyRow(sheet, rowIndex+1, cLength);
//		Region region = new Region(rowIndex, (short) 0, rowIndex+1, (short)(cLength-1));
		CellRangeAddress region  = new CellRangeAddress(rowIndex, 0, rowIndex+1, cLength-1);
		sheet.addMergedRegion(region);
		return row;
	}
	
	protected void export(HttpServletRequest request, HttpServletResponse response, String fileName, String[] header, List<T> list) {
		this.export(request, response, fileName, header, new short[]{}, list);
	}
	
	protected void export(HttpServletRequest request, HttpServletResponse response, String fileName, String[] header, short[] cWidth, List<T> list) {
		if(request == null || response == null || StringUtil.isNull(fileName) || header == null || header.length == 0) return;
		
		HSSFWorkbook wb = new HSSFWorkbook();
		HSSFCellStyle tStyle = createStyle(wb, 0);
		HSSFCellStyle hStyle = createStyle(wb, 1);
		HSSFCellStyle cStyle = createStyle(wb, 2);
		
		HSSFSheet sheet = wb.createSheet();
		wb.setSheetName(0, fileName);
		HSSFCell ce = null;
		int len = header.length;
		if(cWidth == null || cWidth.length != len) {
			cWidth = new short[len];
			for(int i=0; i<len; i++){
				cWidth[i] = 1024 * 5;
			}
		}
		HSSFRow row = createTitleRow(sheet, 0, len, tStyle, fileName);
		
		row = sheet.createRow(2);
		for(int i=0; i<len; i++){
			ce = row.createCell((short)i);
			ce.setCellStyle(hStyle);
			ce.setCellType(CellType.STRING);
			ce.setCellValue(header[i]);
			sheet.setColumnWidth((short)i, (short)cWidth[i]);
		}
		
		initRows(sheet, list, len, cStyle);
		
		ServletOutputStream out = null;
		fileName = fileName.endsWith(SUFFIX) ? fileName : (fileName + SUFFIX);
		try {
			out = response.getOutputStream();
			initOut(request, response, fileName);
			wb.write(out);
            out.flush();
		} catch (Exception e) {
			writeLog(e);
		} finally {
			IOUtils.closeQuietly(out);
	    }
	}
	
	private void initOut(HttpServletRequest request, HttpServletResponse response, String fileName) {
		try{
			request.setCharacterEncoding(ENCODING);
			response.setContentType("application/x-msdownload; charset="+ENCODING);
			response.setHeader("Content-disposition", "attachment;filename=\"" + new String(fileName.getBytes("GBK"),"iso8859-1") + "\"");
		} catch(Exception e){}
	}
	
	private void initRows(HSSFSheet sheet, List<T> list, int len, HSSFCellStyle style) {
		if(list == null || list.size() == 0) return;
		HSSFRow row = null;
		HSSFCell ce = null;
		T bean = null;
		for(int i=0; i<list.size(); i++) {
			bean = list.get(i);
			row = sheet.createRow(i+3);
			for(int j=0; j<len; j++){
				ce = row.createCell((short)j);
				ce.setCellStyle(style);
				ce.setCellType(CellType.STRING);
				ce.setCellValue(getValue(i+3, j, bean));
			}
		}
	}
	
	protected void saveBean(HSSFRow row) {}
	
	protected String getValue(int rowIndex, int index, T bean) {
		return "";
	}
	
	protected Map<String, Comparable> getParamMap(HttpServletRequest request) {
		Map<String, Comparable> map = new HashMap<String, Comparable>();
		String[] querys = StringUtil.vString(request.getQueryString()).split("\\&");
		String[] params = null;
		for(String query : querys) {
			params = query.split("\\=");
			if(params.length != 2) continue;
			map.put("like_"+StringUtil.getURLDecode(params[0]), StringUtil.getURLDecode(params[1]));
		}
		return map;
	}
	
	protected void closeWindow(HttpServletResponse response) throws IOException {
		executeJavascript(response, new StringBuffer()
			.append("var parentWin = parent.parent.getParentWindow(parent);")
			.append("parentWin._table.reLoad();")
			.append("parentWin.closeDialog();")
			.toString());
	}
	
	protected void executeJavascript(HttpServletResponse response, String content) throws IOException {
		PrintWriter out = response.getWriter();
		out.println("<script type=\"text/javascript\">");
		out.println(content);
		out.println("</script>");
		out.close();
	}
}
