package com.platform.controller;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;





import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.log4j.Logger;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import org.springframework.web.multipart.commons.CommonsMultipartResolver;

import com.base.BaseController;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.platform.entities.PreDataInfo;
import com.platform.entities.ResumableInfo;
import com.platform.entities.ResumableInfoStorage;
import com.platform.form.PagerOptions;
import com.platform.service.IPreDataInfoService;
import com.platform.utils.Configs;
import com.platform.utils.FileOperateHelper;
import com.platform.utils.HttpUtils;
import com.platform.utils.ThreadRemoveFile;
import com.platform.utils.UtilsHelper;

/** 信息系统--清单（包含excel操作）
 * @author chen
 *
 */
@Controller
@RequestMapping("/fileOperation")
public class ExcelController extends BaseController{
	
	private static ObjectMapper mapper = new ObjectMapper();
	/**
	 * 日志
	 */
	public final static Logger log = Logger.getLogger(ExcelController.class);
	
	/**
	 * 信息系统--清单--业务类
	 */
	@Resource(name = "preDataInfoService")
	private IPreDataInfoService preDataInfoService;

	/** 信息系统--清单--文件上传处理函数
	 * @param request
	 * @param response
	 * @throws ServletException
	 * @throws IOException
	 */
	@RequestMapping(value = "/file/upload", method = RequestMethod.POST)
	public void upload(HttpServletRequest request, HttpServletResponse response)
		throws ServletException, IOException {

		int resumableChunkNumber = HttpUtils.toInt(
				request.getParameter("resumableChunkNumber"), -1);
		ResumableInfo info = getResumableInfo(request);
	
		String requestMethod = request.getMethod();
		// 处理GET请求
		if ("GET".equals(requestMethod)) {
			if (info.uploadedChunks
					.contains(new ResumableInfo.ResumableChunkNumber(
							resumableChunkNumber))) {
				response.getWriter().print("Uploaded."); // This Chunk has been
															// Uploaded.
			} else {
				response.setStatus(HttpServletResponse.SC_NOT_FOUND);
			}
		} else if ("POST".equals(requestMethod)) { // 处理POST请求
			RandomAccessFile raf = new RandomAccessFile(info.resumableFilePath,
					"rw");
			// Seek to position
			raf.seek((resumableChunkNumber - 1)
					* (long) info.resumableChunkSize);
	
			// Save to file
			InputStream is = request.getInputStream();
			long readed = 0;
			long contentLength = request.getContentLength();
			byte[] bytes = new byte[1024 * 100];
			while (readed < contentLength) {
				int r = is.read(bytes);
				if (r < 0) {
					break;
				}
				raf.write(bytes, 0, r);
				readed += r;
			}
			raf.close();
	
			// Mark as uploaded.
			info.uploadedChunks.add(new ResumableInfo.ResumableChunkNumber(
					resumableChunkNumber));
			if (info.checkIfUploadFinished()) { // Check if all chunks uploaded,
												// and change filename
				log.info(info.resumableFilename);
				ResumableInfoStorage.getInstance().remove(info);
				response.getWriter().print("All finished.");
				
			} else {
				response.getWriter().print("Upload");
			}
		} else { // 不处理非GET/POST请求
			throw new IllegalStateException("只接受 POST或GET请求");
		}
		log.info("----");
	}
	
	/** 信息系统--清单--文件下载处理函数(导出excel)
	 * @param request
	 * @param response
	 * @return
	 * @throws Exception
	 */
	@RequestMapping(value = "/file/download")
	public ResponseEntity<byte[]> download(HttpServletRequest request,
			HttpServletResponse response) throws Exception {
		//先导出
		preDataInfoService.exportExcel(Configs.FILE_DOWNLOAD_PATH);
		
		File file = new File(Configs.FILE_DOWNLOAD_PATH);
		if (file.exists()) {
			HttpHeaders headers = new HttpHeaders();
			String fileName = new String(file.getName().getBytes("UTF-8"),
					"iso-8859-1");// 为了解决中文名称乱码问题
			headers.setContentDispositionFormData("attachment", fileName);			
			headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
			return new ResponseEntity<byte[]>(
					FileUtils.readFileToByteArray(file), headers,
					HttpStatus.CREATED);
		} else {
			response.setStatus(500);
			return null;
		}
	}

	/** 文件上传处理函数
	 * @param request
	 * @return
	 * @throws ServletException
	 * @throws IOException
	 */
	private ResumableInfo getResumableInfo(HttpServletRequest request)
			throws ServletException, IOException {
		String base_dir = Configs.FILE_UPLOAD_PATH;

		int resumableChunkSize = HttpUtils.toInt(
				request.getParameter("resumableChunkSize"), -1);
		long resumableTotalSize = HttpUtils.toLong(
				request.getParameter("resumableTotalSize"), -1);
		String resumableIdentifier = request
				.getParameter("resumableIdentifier");
		String fileName = new String(request.getParameter("resumableFilename").getBytes("iso-8859-1"),
				"UTF-8");// 为了解决中文名称乱码问题
		String resumableFilename = fileName /*request.getParameter("resumableFilename")*/;
		String resumableRelativePath = request
				.getParameter("resumableRelativePath");
		// Here we add a ".temp" to every upload file to indicate NON-FINISHED
		new File(base_dir).mkdir();
		String resumableFilePath = new File(base_dir, resumableFilename)
				.getAbsolutePath() + ".temp";

		ResumableInfoStorage storage = ResumableInfoStorage.getInstance();

		ResumableInfo info = storage.get(resumableChunkSize,
				resumableTotalSize, resumableIdentifier, resumableFilename,
				resumableRelativePath, resumableFilePath);
		if (!info.vaild()) {
			storage.remove(info);
			throw new ServletException("Invalid request params.");
		}
		return info;
	}

	/** 信息系统--清单--条件查询
	 * @param res
	 * @param req
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping("/findByParam")
	public ModelMap findByParam(HttpServletRequest res, HttpServletResponse req) throws Exception {
		ModelMap modelMap = new ModelMap();
		
		res.setCharacterEncoding("UTF-8");
		Map<String, String[]> paramMap = res.getParameterMap();
		Set<String> keySet = paramMap.keySet();
		Map<String, String> params = new HashMap<String, String>();
		StringBuffer sb = new StringBuffer().append("当前的请求参数:{");
		for (String str : keySet) {
			String value = paramMap.get(str)[0];
			if (StringUtils.isNotEmpty(value)) {
				params.put(str, value);
				sb.append(str).append(":").append(value).append(",");
			} else {
				sb.append(str).append(":").append("null").append(",");
			}
		}
		Configs.CONSOLE_LOGGER.info(sb.deleteCharAt(sb.length() - 1)
				.append("}").toString());
		PagerOptions pagerOptions = (PagerOptions) UtilsHelper
				.newObjAndSetAttrsByClass(PagerOptions.class, params);
		
		List<PreDataInfo> result = preDataInfoService.findByParam(pagerOptions);
		modelMap.addAttribute("data", result);
		modelMap.addAttribute("length", result.size());
		return modelMap;
	}
	
	/** 信息系统--清单--查询所有
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping("/findAll")
	public ModelMap findAll() throws Exception {
		ModelMap modelMap = new ModelMap();
		List<PreDataInfo> result = preDataInfoService.findAll();
		modelMap.addAttribute("data", result);
		modelMap.addAttribute("length", result.size());
		return modelMap;
	}
	
	/** 信息系统--清单--导入excel
	 * @param request
	 * @param response
	 * @param fileNameList
	 * @return
	 * @throws Exception
	 */
	@ResponseBody
	@RequestMapping(produces = "application/json", value = "/importExcel", method = RequestMethod.POST)
	public ModelMap importExcel(HttpServletRequest request,
            HttpServletResponse response, @RequestBody String fileNameList) throws Exception {
		log.info("---importExcel---" + fileNameList);
		List<String> jsonlist = mapper.readValue(fileNameList, new TypeReference<List<String>>() {}); 
//		JavaType javaType = mapper.getTypeFactory().constructParametricType(List.class, String.class);
		
//		JSONArray jsonArray = JSONArray.fromObject(fileNameList);
//		List<String> jsonlist = (List<String>) JSONArray.toCollection(jsonArray, String.class);
		
		ModelMap modelMap = new ModelMap();
		if (null == jsonlist || jsonlist.size() == 0) {
			modelMap.addAttribute("returncode","3002");
			return modelMap;
		}
		log.info(jsonlist.size());
		List<String> listPath = new ArrayList<String>();
		// 末尾 含有 /(linux)
		// 加上 最后 的 / 
		String dirPath = FileOperateHelper.addLastSeparator(Configs.FILE_UPLOAD_PATH);;
		for (String p : jsonlist) {
			listPath.add(dirPath + p);
		}
		Map<String, List> result = new HashMap<String, List>();
		if (listPath.size() > 0) {
			//导入
			result = preDataInfoService.importExcel(listPath);
			//失败
			if (result.containsKey("fileUnExist")/* || result.containsKey("areaUnImport")*/) {
				modelMap.addAttribute("data", result);
				modelMap.addAttribute("code","3001");
				response.setStatus(500);
			}
			//成功
			else {
				List<PreDataInfo> datalist = preDataInfoService.findAll();
				modelMap.addAttribute("data", datalist);
				modelMap.addAttribute("length", datalist.size());
				modelMap.addAttribute("code","1001");
			}
			//删除文件
			List<String> failedDelete = new ArrayList<String>();
			for (String filePath : listPath) {
				//读取完后删除源文件（不管是否成功导入）
				File tmpf = new File(filePath + ".temp");
				File f = new File(filePath);
				if(!tmpf.delete()){
					failedDelete.add(tmpf.getAbsolutePath());
				}
				if(!f.delete()){
					failedDelete.add(f.getAbsolutePath());
				}
			}
			//删除失败时--启用线程去删除
			new ThreadRemoveFile(failedDelete).start();
		}
		log.info("success : "+modelMap);
		return modelMap;
	}
	
	public void  uploadSpring(HttpServletRequest request, HttpServletResponse respone){
		//解析器解析request的上下文
		CommonsMultipartResolver multipartResolver =
			new CommonsMultipartResolver(request.getSession().getServletContext());
		  //先判断request中是否包涵multipart类型的数据，
		if(multipartResolver.isMultipart(request)){
			 //再将request中的数据转化成multipart类型的数据
			MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
			Iterator<String> iter = multiRequest.getFileNames();
			while(iter.hasNext()){
				//这里的name为fileItem的alias属性值，相当于form表单中name
				String name= iter.next();
				//根据name值拿取文件
				MultipartFile file = multiRequest.getFile(name);
				if(file != null){
					String fileName = file.getOriginalFilename();
					String path = "D:/test/" + fileName;
					File localFile = new File(path);
					if(!localFile.getParentFile().exists()) {
						 //如果目标文件所在的目录不存在，则创建父目录
						 localFile.getParentFile().mkdirs();
					 }
					//写文件到本地
					try {
						file.transferTo(localFile);
					} catch (IOException e) {
						log.error(e.getStackTrace());
					}
					
				}
			}
		}
	}
}
