package com.goafanti.common.controller;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

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

import org.apache.commons.lang3.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;

import com.goafanti.admin.service.AdminService;
import com.goafanti.admin.service.AttachmentService;
import com.goafanti.common.bo.Error;
import com.goafanti.common.bo.Result;
import com.goafanti.common.constant.ErrorConstants;
import com.goafanti.common.enums.UserType;
import com.goafanti.common.model.User;
import com.goafanti.common.service.DistrictGlossoryService;
import com.goafanti.common.service.FieldGlossoryService;
import com.goafanti.common.service.IndustryCategoryService;
import com.goafanti.common.utils.LoggerUtils;
import com.goafanti.common.utils.MobileMessageUtils;
import com.goafanti.common.utils.PasswordUtil;
import com.goafanti.common.utils.PictureUtils;
import com.goafanti.common.utils.TimeUtils;
import com.goafanti.common.utils.VerifyCodeUtils;
import com.goafanti.core.shiro.token.TokenManager;
import com.goafanti.user.service.UserService;

@Controller
@Scope(value = "prototype")
@RequestMapping("/open")
public class PublicController extends BaseController {
	@Value(value = "${accessKey}")
	private String					accessKey			= null;

	@Value(value = "${accessSecret}")
	private String					accessSecret		= null;

	@Value(value = "${upload.path}")
	private String					uploadPath			= null;

	@Value(value = "${upload.private.path}")
	private String					uploadPrivatePath	= null;

	@Value(value = "${static.host}")
	private String					staticHost			= null;

	@Value(value = "${mobileCodeTemplate}")
	private String					mobileCodeTemplate	= null;
	
	@Value(value = "${mobileRemindCodeTemplate}")
	private String					mobileRemindCodeTemplate	= null;

	@Resource
	private UserService				userService;

	@Resource
	private AttachmentService			aftFileService;
	@Resource
	private AdminService	adminService;
	
	@Resource
	private FieldGlossoryService			fieldGlossoryService;

	@Autowired
	private IndustryCategoryService	industryCategoryService;

	@Autowired
	private DistrictGlossoryService	districtGlossoryService;

	@Value(value = "${patentTemplate}")
	private String					patentTemplate		= null;

	@Resource(name = "passwordUtil")
	private PasswordUtil			passwordUtil;
	
	
	


	/**
	 * 获取验证码
	 * 
	 * @param response
	 */
	@RequestMapping(value = "/getVCode", method = RequestMethod.GET)
	public void getVCode(HttpServletResponse response, HttpServletRequest request) {
		try {
			response.setHeader("Pragma", "No-cache");
			response.setHeader("Cache-Control", "no-cache");
			response.setDateHeader("Expires", 0);
			response.setContentType("image/jpg");

			// 生成随机字串
			String verifyCode = VerifyCodeUtils.generateVerifyCode(4);
			// 存入Shiro会话session
			TokenManager.setVal2Session(VerifyCodeUtils.V_CODE, verifyCode.toLowerCase());
			// 生成图片
			int w = 146, h = 33;
			VerifyCodeUtils.outputImage(w, h, response.getOutputStream(), verifyCode);
		} catch (Exception e) {
			LoggerUtils.fmtError(getClass(), e, "获取验证码异常：%s", e.getMessage());
		}
	}

	/**
	 * 手机验证码
	 * 
	 * @param mobile
	 * @param sign
	 *            是否用与找回密码
	 * @param type
	 * @return
	 */
	@RequestMapping(value = "/getMCode", method = RequestMethod.GET)
	@ResponseBody
	public Result getMcode(String mobile, boolean sign, Integer type, String verificationCode) {
		Result res = new Result();
		// 用于找回密码
		if (sign) {
			if (null == userService.selectByMobieAndType(mobile.trim(), type)) {
				res.getError().add(buildError(ErrorConstants.NON_REGISTER, "", "该用户未注册！"));
				return res;
			}
		}

		if (!sign) {
			if (StringUtils.isBlank(verificationCode)) {
				res.getError().add(buildError(ErrorConstants.VCODE_EMPTY_ERROR, "", "图像验证码不能为空！"));
				return res;
			}
			if (!VerifyCodeUtils.verifyCode(verificationCode)) {
				res.getError().add(buildError(ErrorConstants.VCODE_ERROR, "", "图形验证码输入错误！"));
				return res;
			}
		}

		if (TokenManager.getSession().getAttribute(VerifyCodeUtils.M_CODE_TIME) == null
				|| TokenManager.getSession().getAttribute(VerifyCodeUtils.M_CODE_TIME) == "") {
			sendMessage(mobile, res,VerifyCodeUtils.M_CODE);
		} else if (TimeUtils.checkOverTime("getMCode")) {
			VerifyCodeUtils.clearMobileCode();
			VerifyCodeUtils.clearMobileCodeTime();
			sendMessage(mobile, res,VerifyCodeUtils.M_CODE);
		} else {
			res.getError().add(buildError(ErrorConstants.MCODE_FREQUENCY_ERROR, "", "手机验证码发送频繁!"));
		}

		return res;
	}

	/**
	 * 
	 * @param mobile
	 * @param res
	 * @return
	 */
	private Result sendMessage(String mobile, Result res,String codeType) {
		String mobileVerifyCode = VerifyCodeUtils.generateMobileVerifyCode(6); // 生成随机字串
		if(VerifyCodeUtils.M_CODE.equals(codeType)){
			TokenManager.setVal2Session(VerifyCodeUtils.M_CODE, mobileVerifyCode);// 存入Shiro会话session
			TokenManager.setVal2Session(VerifyCodeUtils.M_CODE_TIME, System.currentTimeMillis());
		}else if(VerifyCodeUtils.RESET_CODE.equals(codeType)){
			TokenManager.setVal2Session(VerifyCodeUtils.RESET_CODE, mobileVerifyCode);// 存入Shiro会话session
			TokenManager.setVal2Session(VerifyCodeUtils.RESET_CODE_TIME, System.currentTimeMillis());
		}
		String paramString = "{\"code\":\"" + mobileVerifyCode + "\",\"product\":\"技淘网\"}";
		String ret = MobileMessageUtils.sendMessage(mobileCodeTemplate, paramString, mobile, accessKey, accessSecret);
		if (StringUtils.isNotBlank(ret)) {
			res.getError().add(buildError(ErrorConstants.M_CODE_ERROR));
		}
		return res;
	}

	/**
	 * 下载图片
	 * 
	 * @param response
	 * @param path
	 * @param request
	 */
	@RequestMapping(value = "/downLoadPicture", method = RequestMethod.GET)
	public Result downLoadPicture(HttpServletResponse response, String path, HttpServletRequest request) {
		Result res = new Result();
		if (StringUtils.isBlank(path)) {
			res.getError().add(buildError(ErrorConstants.FILE_NON_EXISTENT));
			return res;
		}
		String filename = Long.toString(System.nanoTime()) + ".jpg";
		InputStream in = null;
		OutputStream out = null;
		byte[] buffer = new byte[8 * 1024];
		String fileSaveRootPath = "";
		try {
			fileSaveRootPath = uploadPrivatePath + path;
			File file = new File(fileSaveRootPath);
			in = new FileInputStream(file);
			out = response.getOutputStream();
			// 设置文件MIME类型
			response.setContentType("application/octet-stream");
			response.setHeader("Content-Disposition", "attachment; filename=" + filename);
			for (;;) {
				int bytes = in.read(buffer);
				if (bytes == -1) {
					break;
				}
				out.write(buffer, 0, bytes);
			}
		} catch (IOException e) {
			LoggerUtils.fmtError(getClass(), e, "IO错误：%s", e.getMessage());
		} finally {
			try {
				if (null != in) {
					in.close();
				}
			} catch (IOException e) {
				LoggerUtils.fmtError(getClass(), e, "IO错误：%s", e.getMessage());
			}
			try {
				if (null != out) {
					out.close();
				}
			} catch (IOException e) {
				LoggerUtils.fmtError(getClass(), e, "IO错误：%s", e.getMessage());
			}
		}
		return res;
	}

	/**
	 * 删除图片文件(public图片)
	 * 
	 * @param path
	 * @return
	 */
	@RequestMapping(value = "/deleteUploadPicture", method = RequestMethod.POST)
	public boolean deleteUploadPicture(String path) {
		boolean flag = false;
		path = uploadPath + path;
		File file = new File(path);
		// 判断目录或文件是否存在
		if (!file.exists() || !file.isFile()) { // 不存在返回 false
			return flag;
		} else {
			return file.delete();
		}
	}

	/**
	 * 获取并输出private图片
	 */
	@RequestMapping(value = "/writeImage", method = RequestMethod.GET)
	public void writeImage(HttpServletResponse response, HttpServletRequest request, String path) {
		try {
			String realPath = uploadPrivatePath + path;
			PictureUtils.outputImage(response, realPath);
		} catch (IOException e) {
			LoggerUtils.fmtError(getClass(), e, "获取图片异常：%s", e.getMessage());
		}
	}

	/**
	 * 下载文件
	 * 
	 * @param res
	 * @param fileName
	 * @param response
	 * @param path
	 * @param request
	 * @return
	 */
	@RequestMapping(value = "/downloadFile", method = RequestMethod.GET)
	public Result downloadFile(String fileName, HttpServletResponse response, String path) {
		Result res = new Result();
		return handleDownloadFile(response, fileName, path, res);
	}

	/**
	 * 下载模版文件
	 * 
	 * @param response
	 * @return
	 */
	@RequestMapping(value = "/downloadTemplateFile", method = RequestMethod.GET)
	public Result downloadTemplateFile(HttpServletResponse response, String sign) {
		Result res = new Result();
		String fileName = "";
		String path = aftFileService.selectAftFileBySign(sign).getFilePath();
		String suffix = path.substring(path.lastIndexOf("."));
		if (sign.equals("patent_prory_statement")) {
			fileName = "专利代理委托书模版" + suffix;
		} else {
			fileName = System.nanoTime() + " ";
		}
		if (!StringUtils.isBlank(path)) {
			return handleDownloadFile(response, fileName, path, res);
		} else {
			res.getError().add(buildError(ErrorConstants.FILE_NON_EXISTENT, "", "下载文件不存在!"));
			return res;
		}
	}

	private Result handleDownloadFile(HttpServletResponse response, String fileName, String path, Result res) {
		String fileSaveRootPath = uploadPrivatePath + path;
		InputStream in = null;
		OutputStream out = null;
		byte[] buffer = new byte[8 * 1024];
		try {
			File file = new File(fileSaveRootPath);
			in = new FileInputStream(file);
			out = response.getOutputStream();
			response.setContentType("multipart/form-data");
			fileName = java.net.URLEncoder.encode(fileName, "UTF-8");
			response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
			for (;;) {
				int bytes = in.read(buffer);
				if (bytes == -1) {
					break;
				}
				out.write(buffer, 0, bytes);
			}
		} catch (IOException e) {
			LoggerUtils.fmtError(getClass(), e, "IO错误：%s", e.getMessage());
		} finally {
			try {
				in.close();
			} catch (IOException e) {
				LoggerUtils.fmtError(getClass(), e, "IO错误：%s", e.getMessage());
			}
			try {
				out.close();
			} catch (IOException e) {
				LoggerUtils.fmtError(getClass(), e, "IO错误：%s", e.getMessage());
			}
		}
		return res;
	}

	@RequestMapping(value = "/findIndustryCategory", method = RequestMethod.GET)
	@ResponseBody
	public Result findIndustryCategory(String id, String noCache) {
		Integer pid = 0;
		if (StringUtils.isNumeric(id)) {
			try {
				pid = Integer.parseInt(id);
			} catch (Exception e) {
				pid = 0;
			}
		}
		if (StringUtils.isNotBlank(noCache)) {
			industryCategoryService.clear(pid);
		}
		return new Result().data(industryCategoryService.list(pid));
	}

	@RequestMapping(value = "/findDistrict", method = RequestMethod.GET)
	@ResponseBody
	public Result findDistrictGlossory(String id, String noCache) {
		Integer pid = 0;
		if (StringUtils.isNumeric(id)) {
			try {
				pid = Integer.parseInt(id);
			} catch (Exception e) {
				pid = 0;
			}
		}
		if (StringUtils.isNotBlank(noCache)) {
			districtGlossoryService.clear(pid);
		}
		return new Result().data(districtGlossoryService.list(pid));
	}

	/**
	 * 
	 * @param mobileCode
	 * @return
	 */
	@RequestMapping(value = "/checkMCode", method = RequestMethod.POST)
	@ResponseBody
	public Result checkMCode(String mobileCode) {
		Result res = new Result();

		if (StringUtils.isBlank(mobileCode)) {
			res.getError().add(buildError(ErrorConstants.MCODE_EMPTY_ERROR, "", "手机验证码"));
			return res;
		}
		if (TimeUtils.checkOverTime(VerifyCodeUtils.M_CODE)) {
			res.getError().add(buildError(ErrorConstants.MCODE_OVERTIME_ERROR, "", "手机验证码超时失效！"));
			VerifyCodeUtils.clearMobileCode();
			VerifyCodeUtils.clearMobileCodeTime();
			return res;
		}
		if (!TokenManager.getSession().getAttribute(VerifyCodeUtils.M_CODE).equals(mobileCode)) {
			res.getError().add(buildError(ErrorConstants.MCODE_ERROR, "", "手机验证码错误"));
			return res;
		}
		// resetCode
		if (res.getError().isEmpty()) {
			String resetCode = UUID.randomUUID().toString();
			TokenManager.setVal2Session(VerifyCodeUtils.RESET_CODE, resetCode);
			TokenManager.setVal2Session(VerifyCodeUtils.RESET_CODE_TIME, System.currentTimeMillis());
			res.setData(resetCode);
		}
		return res;

	}

	/**
	 * 重置密码
	 * 
	 * @param resetCode
	 * @param mobile
	 * @param type
	 * @param newPwd
	 * @return
	 */
	@RequestMapping(value = "/resetPwd", method = RequestMethod.POST)
	@ResponseBody
	public Result resetPwd(String resetCode, String mobile, Integer type, String newPwd) {
		Result res = new Result();
		if (TimeUtils.checkOverTime(VerifyCodeUtils.M_CODE)) {
			res.getError().add(buildError(ErrorConstants.RESET_CODE_OVERTIME, "", "页面超时失效,请重新获取验证码！"));
			cleanCodeSession();
			return res;
		}
		if(null == TokenManager.getSession().getAttribute(VerifyCodeUtils.RESET_CODE)){
			res.getError().add(buildError(ErrorConstants.RESET_CODE_OVERTIME, "", "页面超时失效,请重新获取验证码！"));
			cleanCodeSession();
			return res;
		}else if(!TokenManager.getSession().getAttribute(VerifyCodeUtils.RESET_CODE).equals(resetCode)){
			res.getError().add(buildError(ErrorConstants.RESET_CODE_ERROR, "", "验证码错误,请重新获取验证码！"));
			cleanCodeSession();
			return res;
		}
		if (StringUtils.isBlank(newPwd)) {
			res.getError().add(buildError(ErrorConstants.PARAM_EMPTY_ERROR, "", "新密码"));
			return res;
		}

		if (StringUtils.isBlank(mobile)) {
			res.getError().add(buildError(ErrorConstants.PARAM_EMPTY_ERROR, "", "mobile"));
			return res;
		}

		if (!UserType.ORGANIZATION.getCode().equals(type) && !UserType.PERSONAL.getCode().equals(type)) {
			res.getError().add(buildError(ErrorConstants.PARAM_ERROR, "", "type"));
			return res;
		}

		User user = userService.selectByMobieAndType(mobile, type);
		if (null == user) {
			res.getError().add(buildError(ErrorConstants.PARAM_ERROR, "", "mobile"));
			return res;
		}
		user.setPassword(newPwd);
		user.setPassword(passwordUtil.getEncryptPwd(user));
		userService.updateByPrimaryKeySelective(user);
		VerifyCodeUtils.clearResetCode();
		VerifyCodeUtils.clearResetCodeTime();
		return res;
	}

	private void cleanCodeSession() {
		VerifyCodeUtils.clearResetCode();
		VerifyCodeUtils.clearResetCodeTime();
		VerifyCodeUtils.clearMobileCode();
		VerifyCodeUtils.clearMobileCodeTime();
	}
	
	@RequestMapping(value = "/getRegisterMCode", method = RequestMethod.GET )
	@ResponseBody
	public Result getRegisterMCode(String mobile){
		Result res = new Result();
		if (TokenManager.getSession().getAttribute(VerifyCodeUtils.M_CODE_TIME) == null
				|| TokenManager.getSession().getAttribute(VerifyCodeUtils.M_CODE_TIME) == "") {
			sendMessage(mobile, res,VerifyCodeUtils.M_CODE);
		} else if (TimeUtils.checkOverTime("getMCode")) {
			VerifyCodeUtils.clearMobileCode();
			VerifyCodeUtils.clearMobileCodeTime();
			sendMessage(mobile, res,VerifyCodeUtils.M_CODE);
		} else {
			res.getError().add(buildError(ErrorConstants.MCODE_FREQUENCY_ERROR, "", "手机验证码发送频繁!"));
		}
		return res;
	}
	
	@RequestMapping(value = "/getResetMCode", method = RequestMethod.GET )
	@ResponseBody
	public Result getResetMCode(String mobile, Integer type) {
		Result res = new Result();
		if (null == userService.selectByMobieAndType(mobile.trim(), type)) {
			res.getError().add(buildError(ErrorConstants.NON_REGISTER, "", "该用户未注册！"));
			return res;
		}
		if (TokenManager.getSession().getAttribute(VerifyCodeUtils.RESET_CODE_TIME) == null
				|| TokenManager.getSession().getAttribute(VerifyCodeUtils.RESET_CODE_TIME) == "") {
			sendMessage(mobile, res,VerifyCodeUtils.RESET_CODE);
		} else if (TimeUtils.checkOverTime("resetCode")) {
			VerifyCodeUtils.clearMobileCode();
			VerifyCodeUtils.clearMobileCodeTime();
			sendMessage(mobile, res,VerifyCodeUtils.RESET_CODE);
		} else {
			res.getError().add(buildError(ErrorConstants.MCODE_FREQUENCY_ERROR, "", "手机验证码发送频繁!"));
		}
		return res;
	}
	
	/** 省市区查询 **/
	@RequestMapping(value = "/listAllProvince" , method = RequestMethod.POST)
	@ResponseBody
	public Result listAllProvince(){
		Result res = new Result();
		res.setData(districtGlossoryService.getProvince());
		return res;
	}
	@RequestMapping(value = "/listDefaultPassword" , method = RequestMethod.GET)
	@ResponseBody
	public Result listDefaultPassword(String depId){
		Result res=new Result();
		res.setData(adminService.getListDefaultPassword(depId));
		return res;
	}
	
	
	
    /**
     * 导入流水
     * @param file
     * @param request
     * @return
     */
	@SuppressWarnings("unchecked")
	@RequestMapping(value = "/import" , method = RequestMethod.POST)
	@ResponseBody
    public Result importTeacher(@RequestParam(value = "file", required = false) MultipartFile file, HttpServletRequest request) {
		Result res=new Result();
        String fileName = file.getOriginalFilename();
            if (!fileName.matches("^.+\\.(?i)(xls)$") && !fileName.matches("^.+\\.(?i)(xlsx)$")) {
                res.error(new Error("", "格式不正确"));
            }
          //检查文件
          try {
			checkFile(file);
		} catch (IOException e) {
			e.printStackTrace();
		}
          //获得Workbook工作薄对象
          Workbook workbook = getWorkBook(file);
          //创建返回对象，把每行中的值作为一个数组，所有行作为一个集合返回
          List<List<String>> list = new ArrayList<>();
          if(workbook != null){
          for(int sheetNum = 0;sheetNum < workbook.getNumberOfSheets();sheetNum++){
          //获得当前sheet工作表
          Sheet sheet = workbook.getSheetAt(sheetNum);
          if(sheet == null){
          continue;
          }
          //获得当前sheet的开始行
          int firstRowNum = sheet.getFirstRowNum();
          //获得当前sheet的结束行
          int lastRowNum = sheet.getLastRowNum();
          //循环除了第2行的所有行
          for(int rowNum = firstRowNum+2;rowNum <= lastRowNum;rowNum++){
          //获得当前行
          Row row = sheet.getRow(rowNum);
          if(row == null){
          continue;
          }
          //获得当前行的开始列
          int firstCellNum = row.getFirstCellNum();
          //获得当前行的列数
          int lastCellNum = row.getLastCellNum();
          @SuppressWarnings("rawtypes")
		ArrayList arrayList = new ArrayList();
          //循环当前行 cellNum = (firstCellNum+1) 则是除开第一例
          for(int cellNum = (firstCellNum); cellNum < lastCellNum;cellNum++){
          Cell cell = row.getCell(cellNum);
          arrayList.add(getCellValue(cell));
          }
          list.add(arrayList);
          }
          }
          }
          System.out.println(list.toString());
          return res;
          }
          public static void checkFile(MultipartFile file) throws IOException{
          //判断文件是否存在
          if(null == file){
          throw new FileNotFoundException("文件不存在！");
          }
          //获得文件名
          String fileName = file.getOriginalFilename();
          //判断文件是否是excel文件
          if(!fileName.endsWith("xls") && !fileName.endsWith("xlsx")){
          throw new IOException(fileName + "不是excel文件");
          }
          }
          public static Workbook getWorkBook(MultipartFile file) {
          //创建Workbook工作薄对象，表示整个excel
          Workbook workbook = null;
          try {
          //获取excel文件的io流
          InputStream is = file.getInputStream();
          //如果是xls，使用HSSFWorkbook；如果是xlsx，使用XSSFWorkbook
          workbook = new XSSFWorkbook(is);
          } catch (IOException e) {
          }
          return workbook;
          }
          @SuppressWarnings("deprecation")
		public static String getCellValue(Cell cell){
          String cellValue = "";
          if(cell == null){
          return cellValue;
          }
          //把数字当成String来读，避免出现1读成1.0的情况
          if(cell.getCellType() == Cell.CELL_TYPE_NUMERIC){
          cell.setCellType(Cell.CELL_TYPE_STRING);
          }
          //判断数据的类型
          switch (cell.getCellType()){
          case Cell.CELL_TYPE_NUMERIC: //数字
          cellValue = String.valueOf(cell.getNumericCellValue());
          break;
          case Cell.CELL_TYPE_STRING: //字符串
          cellValue = String.valueOf(cell.getStringCellValue());
          break;
          case Cell.CELL_TYPE_BOOLEAN: //Boolean
          cellValue = String.valueOf(cell.getBooleanCellValue());
          break;
          case Cell.CELL_TYPE_FORMULA: //公式
          cellValue = String.valueOf(cell.getCellFormula());
          break;
          case Cell.CELL_TYPE_BLANK: //空值
          cellValue = "未知";
          break;
          case Cell.CELL_TYPE_ERROR: //故障
          cellValue = "非法字符";
          break;
          default:
          cellValue = "未知类型";
          break;
          }
          return cellValue;
          }
    
            
           

	
}
