package com.ekexiu.portal.service;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.TimeUnit;

import org.jfw.apt.annotation.Autowrie;
import org.jfw.apt.annotation.Nullable;
import org.jfw.apt.web.annotation.Path;
import org.jfw.apt.web.annotation.method.SetCookie;
import org.jfw.apt.web.annotation.operate.Get;
import org.jfw.apt.web.annotation.operate.Post;
import org.jfw.apt.web.annotation.param.JdbcConn;
import org.jfw.apt.web.annotation.param.PathVar;
import org.jfw.util.StringUtil;
import org.jfw.util.context.JfwAppContext;
import org.jfw.util.exception.JfwBaseException;
import org.jfw.util.state.StateCode;

import com.ekexiu.portal.dao.ProfessorDao;
import com.ekexiu.portal.dao.UserDao;
import com.ekexiu.portal.mail.MailService;
import com.ekexiu.portal.mobile.MobilePhoneService;
import com.ekexiu.portal.po.Professor;
import com.ekexiu.portal.po.User;
import com.ekexiu.portal.pojo.SessionUser;

@Path
public class SysService {
	public static final String DEFAULT_PASS_WORD = "11111111111111111111111111111111";

	@Autowrie
	private UserDao userDao;
	@Autowrie
	private ProfessorDao professorDao;
	@Autowrie
	private MailService mailservice;
	@Autowrie
	private MobilePhoneService mobilePhoneServcie;

	private String bindMailSubject;

	private String bindMailReplaceKey;
	private String bindMailReplaceContentTempalte;
	private long timeLimitWithBindMail = 10 * 60 * 1000;

	private String regMailReplaceKey;
	private String regMailReplaceContentTempalte;
	private long timeLimitWithRegMail = 10 * 60 * 1000;

	private String bindMobilePhoneReplaceKey;
	private String bindMobilePhoneContentTemplate;
	private long timeLimitWithBindMobilePhone = 3 * 60 * 1000;

	private String phoneRetrievePasswordReplaceKey;
	private String phoneRetrievePasswordContentTemplate;
	private long timeLimitWithPhoneRetrievePassword = 3 * 60 * 1000;

	private String mailRetrievePasswordContentTemplate;
	private String mailRetrievePasswordReplaceKey;
	private String mailRetrievePasswordSubject;
	private long timeLimitWithMailRetrivePassword = 10 * 60 * 1000;

	private String regMobilePhoneReplaceKey;
	private String regMobilePhoneContentTemplate;
	private long timeLimitWithRegMobilePhone = 3 * 60 * 1000;

	public String getRegMailReplaceKey() {
		return regMailReplaceKey;
	}

	public void setRegMailReplaceKey(String regMailReplaceKey) {
		this.regMailReplaceKey = regMailReplaceKey;
	}

	public String getRegMailReplaceContentTempalte() {
		return regMailReplaceContentTempalte;
	}

	public void setRegMailReplaceContentTempalte(
			String regMailReplaceContentTempalte) {
		this.regMailReplaceContentTempalte = regMailReplaceContentTempalte;
	}

	public long getTimeLimitWithRegMail() {
		return timeLimitWithRegMail;
	}

	public void setTimeLimitWithRegMail(long timeLimitWithRegMail) {
		this.timeLimitWithRegMail = timeLimitWithRegMail;
	}

	public String getRegMobilePhoneReplaceKey() {
		return regMobilePhoneReplaceKey;
	}

	public void setRegMobilePhoneReplaceKey(String regMobilePhoneReplaceKey) {
		this.regMobilePhoneReplaceKey = regMobilePhoneReplaceKey;
	}

	public String getRegMobilePhoneContentTemplate() {
		return regMobilePhoneContentTemplate;
	}

	public void setRegMobilePhoneContentTemplate(
			String regMobilePhoneContentTemplate) {
		this.regMobilePhoneContentTemplate = regMobilePhoneContentTemplate;
	}

	public long getTimeLimitWithRegMobilePhone() {
		return timeLimitWithRegMobilePhone;
	}

	public void setTimeLimitWithRegMobilePhone(long timeLimitWithRegMobilePhone) {
		this.timeLimitWithRegMobilePhone = timeLimitWithRegMobilePhone;
	}

	public String getMailRetrievePasswordSubject() {
		return mailRetrievePasswordSubject;
	}

	public void setMailRetrievePasswordSubject(
			String mailRetrievePasswordSubject) {
		this.mailRetrievePasswordSubject = mailRetrievePasswordSubject;
	}

	public MobilePhoneService getMobilePhoneServcie() {
		return mobilePhoneServcie;
	}

	public void setMobilePhoneServcie(MobilePhoneService mobilePhoneServcie) {
		this.mobilePhoneServcie = mobilePhoneServcie;
	}

	public String getPhoneRetrievePasswordReplaceKey() {
		return phoneRetrievePasswordReplaceKey;
	}

	public void setPhoneRetrievePasswordReplaceKey(
			String phoneRetrievePasswordReplaceKey) {
		this.phoneRetrievePasswordReplaceKey = phoneRetrievePasswordReplaceKey;
	}

	public String getPhoneRetrievePasswordContentTemplate() {
		return phoneRetrievePasswordContentTemplate;
	}

	public void setPhoneRetrievePasswordContentTemplate(
			String phoneRetrievePasswordContentTemplate) {
		this.phoneRetrievePasswordContentTemplate = phoneRetrievePasswordContentTemplate;
	}

	public long getTimeLimitWithPhoneRetrievePassword() {
		return timeLimitWithPhoneRetrievePassword;
	}

	public void setTimeLimitWithPhoneRetrievePassword(
			long timeLimitWithPhoneRetrievePassword) {
		this.timeLimitWithPhoneRetrievePassword = timeLimitWithPhoneRetrievePassword;
	}

	public long getTimeLimitWithMailRetrivePassword() {
		return timeLimitWithMailRetrivePassword;
	}

	public void setTimeLimitWithMailRetrivePassword(
			long timeLimitWithMailRetrivePassword) {
		this.timeLimitWithMailRetrivePassword = timeLimitWithMailRetrivePassword;
	}

	public String getBindMobilePhoneReplaceKey() {
		return bindMobilePhoneReplaceKey;
	}

	public void setBindMobilePhoneReplaceKey(String bindMobilePhoneReplaceKey) {
		this.bindMobilePhoneReplaceKey = bindMobilePhoneReplaceKey;
	}

	public String getBindMobilePhoneContentTemplate() {
		return bindMobilePhoneContentTemplate;
	}

	public void setBindMobilePhoneContentTemplate(
			String bindMobilePhoneContentTemplate) {
		this.bindMobilePhoneContentTemplate = bindMobilePhoneContentTemplate;
	}

	public long getTimeLimitWithBindMobilePhone() {
		return timeLimitWithBindMobilePhone;
	}

	public void setTimeLimitWithBindMobilePhone(
			long timeLimitWithBindMobilePhone) {
		this.timeLimitWithBindMobilePhone = timeLimitWithBindMobilePhone;
	}

	public void setMailRetrievePasswordContentTemplate(
			String retrievePasswordContentTemplate) {
		this.mailRetrievePasswordContentTemplate = retrievePasswordContentTemplate;
	}

	public String getBindMailSubject() {
		return bindMailSubject;
	}

	public void setBindMailSubject(String bindMailSubject) {
		this.bindMailSubject = bindMailSubject;
	}

	public long getTimeLimitWithBindMail() {
		return timeLimitWithBindMail;
	}

	public void setTimeLimitWithBindMail(long timeLimitWithBindMail) {
		this.timeLimitWithBindMail = timeLimitWithBindMail;
	}

	public String getMailRetrievePasswordReplaceKey() {
		return mailRetrievePasswordReplaceKey;
	}

	public void setMailRetrievePasswordReplaceKey(
			String retrievePasswordReplaceKey) {
		this.mailRetrievePasswordReplaceKey = retrievePasswordReplaceKey;
	}

	public String getBindMailReplaceKey() {
		return bindMailReplaceKey;
	}

	public void setBindMailReplaceKey(String bindMailReplaceKey) {
		this.bindMailReplaceKey = bindMailReplaceKey;
	}

	public String getMailRetrievePasswordContentTemplate() {
		return mailRetrievePasswordContentTemplate;
	}

	public String getBindMailReplaceContentTempalte() {
		return bindMailReplaceContentTempalte;
	}

	public void setBindMailReplaceContentTempalte(
			String bindMailReplaceContentTempalte) {
		this.bindMailReplaceContentTempalte = bindMailReplaceContentTempalte;
	}

	public UserDao getUserDao() {
		return userDao;
	}

	public ProfessorDao getProfessorDao() {
		return professorDao;
	}

	public void setProfessorDao(ProfessorDao professorDao) {
		this.professorDao = professorDao;
	}

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	public MailService getMailservice() {
		return mailservice;
	}

	public void setMailservice(MailService mailservice) {
		this.mailservice = mailservice;
	}

	@Get
	@Path("/getUUID")
	public String getUUID(@JdbcConn Connection con, String pass)
			throws SQLException {
		return StringUtil.md5(pass);
	}

	/**
	 * 验证注册时填写的手机号和邮箱是否已经注册过
	 * @param con
	 * @param key 手机号或邮箱
	 * @return 如果该手机或邮箱已经注册过返回false， 否则返回true
	 * @throws SQLException
	 */
	@Get
	@Path("/isReg")
	public boolean isReg(@JdbcConn Connection con, String key)
			throws SQLException {
		User user = this.userDao.queryByEmailOrMobilePhone(con, key);
		if (null != user) {
			return false;
		} else {
			return true;
		}
	}
	
	@Get
	@Path("/qaUser")
	public User queryUser(@JdbcConn Connection con, String id) throws SQLException{
		User user =  this.userDao.query(con, id);
		User user2 = new User();
		user2.setId(user.getId());
		user2.setMobilePhone(user.getMobilePhone());
		user2.setEmail(user.getEmail());
		return user2;
	}

	/**
	 * 手机验证注册
	 * 
	 * @param con
	 * @param state
	 *            发送手机验证码的返回值
	 * @param mobilePhone
	 *            验证的手机号
	 * @param validateCode
	 *            手机验证码
	 * @param password
	 *            注册密码
	 * @return
	 * @throws SQLException
	 * @throws JfwBaseException 
	 */
	@Post
	@Path("/regmobile")
	public String regMobile(@JdbcConn(true) Connection con, String state,
			String mobilePhone, String validateCode, String password)
			throws SQLException, JfwBaseException {
		@SuppressWarnings("unchecked")
		StateCode<String, String> sc = (StateCode<String, String>) JfwAppContext
				.getCachedObject(state);
		if (sc == null)
			return "验证超时";
		if (sc.getExpiredTime() < System.currentTimeMillis())
			return "验证超时";
		try {
			if (!sc.getKey().equals(mobilePhone)) {
				return "手机号与验证手机不匹配";
			}
			if (!sc.getValue().equals(validateCode)) {
				return "验证码错误";
			}
			User user = new User();
			user.setId(StringUtil.buildUUID());
			String passwd = StringUtil.md5(password);
			user.setMobilePhone(mobilePhone);
			user.setPasswd(passwd);
			user.setUserType(0 + "");
			this.userDao.insert(con, user);
			return user.getId();
		} finally {
			JfwAppContext.removeCachedObject(state);
		}
	}

	/**
	 * 邮箱验证
	 * 
	 * @param con
	 * @param key
	 *            发送邮箱验证的返回值
	 * @param mail
	 *            验证的邮箱地址
	 * @return 验证成功 用户登录并返回用户信息 验证失败返回null
	 * @throws SQLException
	 * @throws JfwBaseException 
	 */
	@SetCookie(checkResultNull = true, path = "/", value = {
			"userid=result.getId()", "userMobilePhone=result.getMobilePhone()",
			"userType=result.getType()",
			"userAuth=String.valueOf(result.isAuth())",
			"userEmail=result.getEmail()==null?\"\":result.getEmail()",
			"userName=result.getName()==null?\"\":java.net.URLEncoder.encode(result.getName(),\"utf-8\")" 
			})
	@Post
	@Path("/regmail/{key}")
	public SessionUser regeMail(@JdbcConn(true) Connection con, @PathVar String key, String mail, 
			String userId) throws SQLException, JfwBaseException {
		@SuppressWarnings("unchecked")
		StateCode<String, String> sc = (StateCode<String, String>) JfwAppContext
				.getCachedObject(key);
		if (sc == null) {
			this.userDao.delete(con, userId);
			throw new JfwBaseException("验证超时");
		}
		if (sc.getExpiredTime() < System.currentTimeMillis()) {
			this.userDao.delete(con, userId);
			throw new JfwBaseException("验证超时");
		}
		try {
			User user = userDao.queryByEmailOrMobilePhone(con, mail);
			if (null == user)
				return null;
			SessionUser ret = new SessionUser();
			ret.setId(user.getId());
			if (null != this.professorDao.query(con, user.getId())) {
				ret.setName(this.professorDao.query(con, user.getId()).getName());
			}
			ret.setMobilePhone(user.getMobilePhone());
			ret.setType(user.getUserType());
			ret.setEmail(user.getEmail());
			ret.setAuth(true);
			return ret;
		} finally {
			JfwAppContext.removeCachedObject(key);
		}
	}

	/**
	 * 邮箱注册并发送邮箱验证
	 * @param con
	 * @param mail 待验证的邮箱地址
	 * @param password 密码
	 * @return 注册成功并发动验证返回用户ID  用户已注册返回null  邮件发送失败抛出异常
	 * @throws JfwBaseException
	 * @throws SQLException
	 */
	@Get
	@Path("/regmail")
	public String regMail(@JdbcConn(true) Connection con, String mail,
			String password) throws JfwBaseException, SQLException {
		User user1 = new User();
		User user = this.userDao.queryByEmailOrMobilePhone(con, mail);
		if (null != user) {
			return null;
		} else {
			user1.setId(StringUtil.buildUUID());
			String passwd = StringUtil.md5(password);
			user1.setEmail(mail);
			user1.setPasswd(passwd);
			user1.setUserType(0 + "");
			this.userDao.insert(con, user1);
			this.sendMailReg(con, mail);
		}
		return user1.getId();
	}
	
	@Get
	@Path("/resendMail")
	public boolean sendMailReg(@JdbcConn(false) Connection con, String mail) throws JfwBaseException {
		StateCode<String, String> sc = new StateCode<String, String>();
		final String key = JfwAppContext.cacheObjectAndGenKey(sc);

		Map<String, String> map = new HashMap<String, String>();
		map.put(this.regMailReplaceKey, key);
		try {
			mailservice.sendSimpleMail(mail,
					this.regMailReplaceContentTempalte, map,
					this.bindMailSubject);
			long ct = System.currentTimeMillis();
			long et = ct + this.timeLimitWithRegMail + 10000;
			sc.setBuildTime(ct);
			sc.setExpiredTime(et);
			JfwAppContext.getScheduledExecutorService().schedule(
					new Runnable() {
						@Override
						public void run() {
							JfwAppContext.removeCachedObject(key);
						}
					}, this.timeLimitWithRegMail + 20000,
					TimeUnit.MILLISECONDS);
		} catch (Exception e) {
			JfwAppContext.removeCachedObject(key);
			throw new JfwBaseException(10011, "send mail to " + mail
					+ " error", e);
		}
		return true;
	}

	@SetCookie(checkResultNull = true, path = "/", value = {
			"userid=result.getId()", "userMobilePhone=result.getMobilePhone()",
			"userType=result.getType()",
			"userAuth=String.valueOf(result.isAuth())",
			"userEmail=result.getEmail()==null?\"\":result.getEmail()",
			"userName=result.getName()==null?\"\":java.net.URLEncoder.encode(result.getName(),\"utf-8\")" 
			})
	@Post
	@Path("/slogin")
	public SessionUser sLogin(@JdbcConn Connection con, String code,
			String mobile) throws SQLException {
		User user = userDao.query(con, code);
		if (null == user)
			return null;
		if (!mobile.equals(user.getMobilePhone()))
			return null;
		Professor professor = this.professorDao.query(con, code);
		SessionUser ret = new SessionUser();
		ret.setId(code);
		ret.setMobilePhone(mobile);
		ret.setType(user.getUserType());
		ret.setEmail(user.getEmail());
		ret.setName(professor.getName());
		ret.setAuth(!DEFAULT_PASS_WORD.equals(user.getPasswd()));
		return ret;
	}

	@SetCookie(checkResultNull = true, path = "/", value = {
			"userid=result.getId()", "userMobilePhone=result.getMobilePhone()",
			"userType=result.getType()",
			"userAuth=String.valueOf(result.isAuth())",
			"userEmail=result.getEmail()==null?\"\":result.getEmail()",
			"userName=result.getName()==null?\"\":java.net.URLEncoder.encode(result.getName(),\"utf-8\")"
			})
	@Post
	@Path("/login")
	public SessionUser login(@JdbcConn Connection con, String lk, String pw)
			throws SQLException {
		User user = userDao.queryByEmailOrMobilePhone(con, lk);
		if (null == user)
			throw new SQLException("该用户还未注册");
		if (DEFAULT_PASS_WORD.equals(user.getPasswd()))
			return null;
		if (!StringUtil.md5(pw).equals(user.getPasswd()))
			return null;

		SessionUser ret = new SessionUser();
		ret.setId(user.getId());
		if (null != this.professorDao.query(con, user.getId())) {
			ret.setName(this.professorDao.query(con, user.getId()).getName());
		}
		ret.setMobilePhone(user.getMobilePhone());
		ret.setType(user.getUserType());
		ret.setEmail(user.getEmail());
		ret.setAuth(true);
		return ret;
	}

	@Post
	@Path("/cp")
	public boolean changePw(@JdbcConn(true) Connection con, String id,
			String npw, @Nullable String onw) throws SQLException {
		User user = this.userDao.query(con, id);
		if (user == null)
			return false;
		if (onw == null) {
			if (!DEFAULT_PASS_WORD.equals(user.getPasswd()))
				return false;
		} else {
			if (!StringUtil.md5(onw).equals(user.getPasswd()))
				return false;
		}
		this.userDao.updatePassword(con, StringUtil.md5(npw), id);
		return true;
	}

	@Get
	@Path("/reqBindMail")
	public boolean reqBindMail(@JdbcConn(false) Connection con, String userid,
			String mail) throws JfwBaseException, SQLException {
		User user = this.userDao.query(con, userid);
		if (null == user)
			return false;

		StateCode<String, String> sc = new StateCode<String, String>();
		sc.setKey(userid);
		sc.setValue(mail);
		final String key = JfwAppContext.cacheObjectAndGenKey(sc);

		Map<String, String> map = new HashMap<String, String>();
		map.put(this.bindMailReplaceKey, key);
		try {
			mailservice.sendSimpleMail(mail,
					this.bindMailReplaceContentTempalte, map,
					this.bindMailSubject);
			long ct = System.currentTimeMillis();
			long et = ct + this.timeLimitWithBindMail + 10000;
			sc.setBuildTime(ct);
			sc.setExpiredTime(et);
			JfwAppContext.getScheduledExecutorService().schedule(
					new Runnable() {
						@Override
						public void run() {
							JfwAppContext.removeCachedObject(key);
						}
					}, this.timeLimitWithBindMail + 20000,
					TimeUnit.MILLISECONDS);
		} catch (Exception e) {
			JfwAppContext.removeCachedObject(key);
			throw new JfwBaseException(10011,
					"send mail to " + mail + " error", e);
		}
		return true;
	}

	@Get
	@Path("/bindMail/{key}")
	public boolean bindMail(@JdbcConn(true) Connection con, @PathVar String key)
			throws SQLException, JfwBaseException {
		@SuppressWarnings("unchecked")
		StateCode<String, String> sc = (StateCode<String, String>) JfwAppContext
				.getCachedObject(key);
		if (sc == null)
			return false;
		if (sc.getExpiredTime() < System.currentTimeMillis())
			return false;
		try {
			return this.userDao.updateEmail(con, sc.getValue(), sc.getKey()) > 0;
		} finally {
			JfwAppContext.removeCachedObject(key);
		}
	}

	@Get
	@Path("/vcWithBind")
	public String reqBindBindMobilePhone(@JdbcConn(false) Connection con,
			String userid, String mobilePhone) throws JfwBaseException,
			SQLException {
		User user = this.userDao.query(con, userid);
		if (null == user)
			return null;
		user = this.userDao.queryByEmailOrMobilePhone(con, mobilePhone);
		if (null != user)
			return "该手机号已经绑定其他用户";

		StateCode<String, String> sc = new StateCode<String, String>();

		final String key = JfwAppContext.cacheObjectAndGenKey(sc);

		try {
			Random rd = new Random();
			int vi = rd.nextInt(10000);

			String vc = String.format("%04d", vi);
			sc.setKey(mobilePhone);
			sc.setValue(vc);
			this.mobilePhoneServcie.sendMessage(mobilePhone,
					this.bindMobilePhoneContentTemplate,
					this.bindMobilePhoneReplaceKey, vc);
			long ct = System.currentTimeMillis();
			long et = ct + this.timeLimitWithBindMobilePhone + 5000;
			sc.setBuildTime(ct);
			sc.setExpiredTime(et);
			JfwAppContext.getScheduledExecutorService().schedule(
					new Runnable() {
						@Override
						public void run() {
							JfwAppContext.removeCachedObject(key);
						}
					}, this.timeLimitWithBindMobilePhone + 10000,
					TimeUnit.MILLISECONDS);
		} catch (Exception e) {
			JfwAppContext.removeCachedObject(key);
			throw new JfwBaseException(10012, "send mobile phone message to "
					+ mobilePhone + " error", e);
		}
		return key;
	}

	/**
	 * 发送手机验证码
	 * 
	 * @param con
	 * @param mobilePhone
	 *            验证的手机号
	 * @return
	 * @throws JfwBaseException
	 * @throws SQLException
	 */
	@Get
	@Path("/regmobilephone")
	public String regMobilePhone(@JdbcConn(false) Connection con,
			String mobilePhone) throws JfwBaseException, SQLException {
		User user = this.userDao.queryByEmailOrMobilePhone(con, mobilePhone);
		if (null != user) {
			return null;
		}

		StateCode<String, String> sc = new StateCode<String, String>();

		final String key = JfwAppContext.cacheObjectAndGenKey(sc);

		try {
			Random rd = new Random();
			int vi = rd.nextInt(10000);

			String vc = String.format("%04d", vi);
			sc.setKey(mobilePhone);
			sc.setValue(vc);
			this.mobilePhoneServcie.sendMessage(mobilePhone,
					this.regMobilePhoneContentTemplate,
					this.regMobilePhoneReplaceKey, vc);
			long ct = System.currentTimeMillis();
			long et = ct + this.timeLimitWithRegMobilePhone + 5000;
			sc.setBuildTime(ct);
			sc.setExpiredTime(et);
			JfwAppContext.getScheduledExecutorService().schedule(
					new Runnable() {
						@Override
						public void run() {
							JfwAppContext.removeCachedObject(key);
						}
					}, this.timeLimitWithRegMobilePhone + 10000,
					TimeUnit.MILLISECONDS);
		} catch (Exception e) {
			JfwAppContext.removeCachedObject(key);
			throw new JfwBaseException(10012, "send mobile phone message to "
					+ mobilePhone + " error", e);
		}
		return key;
	}

	@Post
	@Path("/bindMobilePhone")
	public boolean bindMobilePhone(@JdbcConn(true) Connection con,
			String state, String userid, String mobilePhone, String validateCode)
			throws SQLException, JfwBaseException {
		@SuppressWarnings("unchecked")
		StateCode<String, String> sc = (StateCode<String, String>) JfwAppContext
				.getCachedObject(state);
		if (sc == null)
			return false;
		if (sc.getExpiredTime() < System.currentTimeMillis())
			return false;
		try {
			if (!sc.getKey().equals(mobilePhone)
					|| !sc.getValue().equals(validateCode))
				return false;
			return this.userDao.updateMobilePhone(con, mobilePhone, userid) > 0;
		} finally {
			JfwAppContext.removeCachedObject(state);
		}
	}

	@Get
	@Path("/vcWithRP")
	public String rePassWordWithPhone(@JdbcConn(false) Connection con,
			String mobilePhone) throws JfwBaseException, SQLException {

		User user = this.userDao.queryByEmailOrMobilePhone(con, mobilePhone);
		if (null == user)
			return "该手机号还未注册";

		StateCode<String, String> sc = new StateCode<String, String>();
		final String key = JfwAppContext.cacheObjectAndGenKey(sc);
		try {
			Random rd = new Random();
			int vi = rd.nextInt(10000);

			String vc = String.format("%04d", vi);
			sc.setKey(mobilePhone);
			sc.setValue(vc);
			this.mobilePhoneServcie.sendMessage(mobilePhone,
					this.phoneRetrievePasswordContentTemplate,
					this.phoneRetrievePasswordReplaceKey, vc);
			long ct = System.currentTimeMillis();
			long et = ct + this.timeLimitWithPhoneRetrievePassword + 5000;
			sc.setBuildTime(ct);
			sc.setExpiredTime(et);
			JfwAppContext.getScheduledExecutorService().schedule(
					new Runnable() {
						@Override
						public void run() {
							JfwAppContext.removeCachedObject(key);
						}
					}, this.timeLimitWithPhoneRetrievePassword + 10000,
					TimeUnit.MILLISECONDS);
		} catch (Exception e) {
			JfwAppContext.removeCachedObject(key);
			throw new JfwBaseException(10012, "send mobile phone message to "
					+ mobilePhone + " error", e);
		}
		return key;
	}

	@Post
	@Path("/validCode")
	public boolean validCode(String state, String vc) throws JfwBaseException {
		@SuppressWarnings("unchecked")
		StateCode<String, String> sc = (StateCode<String, String>) JfwAppContext
				.getCachedObject(state);
		if (sc == null) {
			throw new JfwBaseException("验证超时");
		}
		if (sc.getExpiredTime() < System.currentTimeMillis()) {
			throw new JfwBaseException("验证超时");
		}
		return sc.getValue().equals(vc);
	}

	@Post
	@Path("/resetPasswordWithMobilePhone")
	public boolean resetPassword(@JdbcConn(true) Connection con, String state,
			String mobilePhone, String pw, String vc) throws SQLException, JfwBaseException {
		@SuppressWarnings("unchecked")
		StateCode<String, String> sc = (StateCode<String, String>) JfwAppContext
				.getCachedObject(state);
		if (sc == null) {
			throw new JfwBaseException("验证超时");
		}
		if (sc.getExpiredTime() < System.currentTimeMillis()) {
			throw new JfwBaseException("验证超时");
		}
		try {
			if (!sc.getKey().equals(mobilePhone) || !sc.getValue().equals(vc))
				return false;
			return this.userDao.updatePasswordWithMobileOrEmail(con,
					StringUtil.md5(pw), mobilePhone) > 0;
		} finally {
			JfwAppContext.removeCachedObject(state);
		}
	}

	@Get
	@Path("/reqRpWithEmail")
	public boolean reqRpWithEmail(@JdbcConn(false) Connection con, String mail)
			throws JfwBaseException, SQLException {
		User user = this.userDao.queryByEmailOrMobilePhone(con, mail);
		if (user == null)
			return false;
		StateCode<String, String> sc = new StateCode<String, String>();
		sc.setKey(user.getId());
		sc.setValue(mail);
		final String key = JfwAppContext.cacheObjectAndGenKey(sc);
		Map<String, String> map = new HashMap<String, String>();
		map.put(this.mailRetrievePasswordReplaceKey, key);
		try {
			mailservice.sendSimpleMail(mail,
					this.mailRetrievePasswordContentTemplate, map,
					this.mailRetrievePasswordSubject);
			long ct = System.currentTimeMillis();
			long et = ct + this.timeLimitWithMailRetrivePassword + 10000;
			sc.setBuildTime(ct);
			sc.setExpiredTime(et);
			JfwAppContext.getScheduledExecutorService().schedule(
					new Runnable() {
						@Override
						public void run() {
							JfwAppContext.removeCachedObject(key);
						}
					}, this.timeLimitWithMailRetrivePassword + 20000,
					TimeUnit.MILLISECONDS);
		} catch (Exception e) {
			JfwAppContext.removeCachedObject(key);
			throw new JfwBaseException(10011,
					"send mail to " + mail + " error", e);
		}
		return true;
	}

	@Get
	@Path("/validMailState")
	public boolean validMailState(String state) {
		@SuppressWarnings("unchecked")
		StateCode<String, String> sc = (StateCode<String, String>) JfwAppContext
				.getCachedObject(state);
		if (sc == null)
			return false;
		if (sc.getExpiredTime() < System.currentTimeMillis())
			return false;
		return true;
	}

	@Post
	@Path("/resetPasswordWith")
	public boolean resetPassword(@JdbcConn(true) Connection con, String state,
			String pw) throws SQLException, JfwBaseException {
		@SuppressWarnings("unchecked")
		StateCode<String, String> sc = (StateCode<String, String>) JfwAppContext
				.getCachedObject(state);
		if (sc == null)
			throw new JfwBaseException("验证超时");
		if (sc.getExpiredTime() < System.currentTimeMillis())
			throw new JfwBaseException("验证超时");
		String key = sc.getKey();
		try {
			return this.userDao.updatePassword(con, StringUtil.md5(pw), key) > 0;
		} finally {
			JfwAppContext.removeCachedObject(state);
		}
	}

	public static void main(String[] args) {
		System.out.println(String.format("%04d", new Random().nextInt(10000)));
	}
}
