package com.wechat.global.filters;

import java.io.IOException;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.stereotype.Component;

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.wechat.common.CommonHelper;
import com.wechat.common.Constants;
import com.wechat.common.utils.StringsUtils;
import com.wechat.global.base.dao.RedisWithExpiryTimeDao;

@Component("loginFilter")
public class LoginFilter implements Filter {

	private static final Log log = LogFactory.getLog(LoginFilter.class);

	@Autowired
	private CommonHelper commonHelper;

	@Autowired
	private RedisWithExpiryTimeDao redisDao;

	@Value("#{configProperties['token.expire.minute']}")
	private int tokenExpireTime;

	@Override
	public void destroy() {
	}

	@Override
	public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain fc)
			throws IOException, ServletException {

		HttpServletRequest req = (HttpServletRequest) servletRequest;

		HttpServletResponse resp = (HttpServletResponse) servletResponse;
		resp.setCharacterEncoding("UTF-8");

		resp.setHeader("Content-type", "text/html;charset=UTF-8");
		// 获取用户ip
		String userIp = commonHelper.getIRealIPAddr(req);

		// 请求中的明文usercode
		String inUserCode = new String();
		if (
				!req.getRequestURI().contains("login/login") 
				&& !req.getRequestURI().contains("login/loginByCode")
				&& !req.getRequestURI().contains("login/unBinding")
				&& !req.getRequestURI().contains("login/binding") 
				&& !req.getRequestURI().contains("login/searchJob")
				&& !req.getRequestURI().contains("login/cooperate")
				&& !req.getRequestURI().contains("login/activation")
				&& !req.getRequestURI().contains("login/getLoginInitImage")
				&& !req.getRequestURI().contains("wxMiniprog/wxMiniLogin")
				&& !req.getRequestURI().contains("wxMiniprog/loginByPhone")
				&& !req.getRequestURI().contains("wxMiniprog/loginByPassword")
				&& !req.getRequestURI().contains("captcha/getNext")
				&& !req.getRequestURI().contains("forgetPassword/forgetPassword")
				&& !req.getRequestURI().contains("verifyCode/getVerifyCode")
				&& !req.getRequestURI().contains("order/aliPay_notify_url")
				&& !req.getRequestURI().contains("order/aliPay_return_url")
				&& !req.getRequestURI().contains("order/weChat_notify_url")
				&& !req.getRequestURI().contains("order/weChat_code_url")
				&& !req.getRequestURI().contains("jsSdk/signature")
				&& !req.getRequestURI().contains("ticket/acquireTicket")
				&& !req.getRequestURI().contains("ticket/getTicketInfo")
				&& !req.getRequestURI().contains("mendunerShow/getTheShow")
				&& !req.getRequestURI().contains("goods/init")
				&& !req.getRequestURI().contains("goods/getPartOfGoodsList")
				&& !req.getRequestURI().contains("position/getDetailNoLogin")
				&& !req.getRequestURI().contains("position/getJobFair")
				&& !req.getRequestURI().contains("position/getFairJobList")
				&& !req.getRequestURI().contains("getBaseData")
				&& !req.getRequestURI().contains("getAdOfJobDtl")
				&& !req.getRequestURI().contains("register")
				&& !req.getRequestURI().contains("getPrepareFlagList")
				&& !req.getRequestURI().contains("noLogin/")
				&& !req.getRequestURI().contains("getStandardTime")
				&& !req.getRequestURI().contains("resetBaseData")
				&& !req.getRequestURI().contains("wxampCallBack")
				) 
		{
			// 没有cookie return
			Cookie[] cookies = req.getCookies();
			if (cookies == null) {
				resp.getWriter().append("{\"result\":100016,\"msg\":\"非法的请求，请允许使用cookie！\"}");
				resp.setStatus(HttpStatus.UNAUTHORIZED.value());
				 resp.getWriter().close();
				return ;
			}
			// cookie 中没有token return
			String token = null;
			for (Cookie cookie : cookies) {
				// 获取token
				if (Constants.TOKEN_COOKIE_NAME.equals(cookie.getName())) {
					token = cookie.getValue();
				}
				// 获取请求的usercode
				if (Constants.TOKEN_USER_ID.equals(cookie.getName())) {
					inUserCode = cookie.getValue();
				}
			}
			if (token == null || token.isEmpty() || StringsUtils.isEmpty(inUserCode)) {
				 resp.getWriter().append("{\"result\":100016,\"msg\":\"非法的请求,token缺失，请关闭页面重新登录！\"}");
				log.error("空的token请求，请求ip：【" + userIp + "】");
				resp.setStatus(HttpStatus.UNAUTHORIZED.value());
				 resp.getWriter().close();
				return ;
			}

			// 重复的请求拦截

			// token 非法 return
			DecodedJWT jwt;
			try {
				JWTVerifier verifier = JWT.require(Algorithm.HMAC512(Constants.TOKEN_KEY)).build();
				jwt = verifier.verify(token);
			} catch (Exception exception) {
				exception.printStackTrace();
				Cookie newCookie = new Cookie(Constants.TOKEN_COOKIE_NAME, null);
				newCookie.setPath("/");
				// 关闭浏览器后cookie失效
				newCookie.setMaxAge(-1);
				resp.addCookie(newCookie);
				resp.getWriter().append("{\"result\":100016,\"msg\":\"登录超时，请重新登录！\"}");
				log.info("登录超时，请求ip：【" + userIp + "】");
				resp.setStatus(HttpStatus.UNAUTHORIZED.value());
				 resp.getWriter().close();	
				return;
			}

			Map<String, Claim> map = jwt.getClaims();
			//用户id和身份标识获取
			String userCode = map.get(Constants.TOKEN_USER_ID).asString();
			String identityFlag = map.get(Constants.TOKEN_IDENTITY_FLAG).asString();
			String creatDate = map.get(Constants.TOKEN_CREATDATE).asString();
			// 如果没有userId和tokenIp就return
			if (!StringsUtils.isEmpty(userCode)) {
				if (userCode.equals(inUserCode)) {
					Cookie newCookie = new Cookie(Constants.TOKEN_COOKIE_NAME, commonHelper.getToken(userCode, identityFlag,creatDate));
					newCookie.setPath("/");
					// token cookie失效时间
					int clearTokenSec = (tokenExpireTime * 60)-1;
					newCookie.setMaxAge(clearTokenSec);
					resp.addCookie(newCookie);
					
					// 设置个人、企业区分
                    Cookie identityCookie = new Cookie(Constants.TOKEN_IDENTITY_FLAG, identityFlag);
                    identityCookie.setPath("/");
                    identityCookie.setMaxAge(-1);
					resp.addCookie(identityCookie);
				} else {
					// 如果ip不正确 或者usercode不正确 就return
					 resp.getWriter().append("{\"result\":100016,\"msg\":\"非法的请求，请关闭页面重新登录！\"}");
					log.error("密文和明文不匹配，请求ip：【" + userIp + "】");
					resp.setStatus(HttpStatus.UNAUTHORIZED.value());
					 resp.getWriter().close();
					return ;
				}
			} else {
				 resp.getWriter().append("{\"result\":100016,\"msg\":\"非法的请求，请关闭页面重新登录！\"}");
				log.error("明文用户code不存在，请求ip：【" + userIp + "】");
				 resp.setStatus(HttpStatus.UNAUTHORIZED.value());
				 resp.getWriter().close();
				 return;
			}
		}
		fc.doFilter(req, resp);

	}

	@Override
	public void init(FilterConfig paramFilterConfig) throws ServletException {
		// ServletContext servletContext = paramFilterConfig.getServletContext();
		// ApplicationContext ctx =
		// WebApplicationContextUtils.getWebApplicationContext(servletContext);
		// commonHelper = (CommonHelper)ctx.getBean("commonHelper");

	}

	/**
	 * 上锁 使用redis 为分布式项目 加锁
	 * 
	 * @param sign
	 * @param tiD
	 * @return
	 * @throws Exception
	 */
	public boolean lock(String sign, String tiD) {
		String uTid = redisDao.select(sign);
		if (uTid == null) {
			redisDao.insertExpMs(sign, tiD, 200);
			return true;
		}
		return false;
	}

	/**
	 * 锁验证
	 * 
	 * @param sign
	 * @param tiD
	 * @return
	 */
	public boolean checklock(String sign, String tiD) {
		String uTid = redisDao.select(sign);
		return tiD.equals(uTid);
	}

	public Map<String, String> getRequstMap(HttpServletRequest req) {
		Map<String, String> params = new HashMap<String, String>();
		Map<String, String[]> requestParams = req.getParameterMap();
		for (Iterator<String> iter = requestParams.keySet().iterator(); iter.hasNext();) {
			String name = (String) iter.next();
			String[] values = (String[]) requestParams.get(name);
			String valueStr = "";
			for (int i = 0; i < values.length; i++) {
				valueStr = (i == values.length - 1) ? valueStr + values[i] : valueStr + values[i] + ",";
			}
			params.put(name, valueStr);
		}
		return params;
	}

}
