package com.apobates.forum.trident.controller.helper;

import java.io.IOException;
import java.util.Arrays;
import java.util.Map;
import java.util.TreeMap;
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.HttpServletRequest;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import com.apobates.forum.trident.vo.TokenMoldBean;
import com.apobates.forum.utils.Commons;
/**
 * 为请求增加token参数
 * 
 * @author xiaofanku
 * @since 20191130
 */
public class RequestTokenParameterFilter implements Filter {
	private final static Logger logger = LoggerFactory.getLogger(RequestTokenParameterFilter.class);
	@Value("${site.domain}")
	private String sitedomain;
	private final static String TS = "token";
	
	public RequestTokenParameterFilter() {
		logger.info("[RTP]init no arg");
	}
	public RequestTokenParameterFilter(String sitedomain) {
		logger.info("[RTP]init inject arg: "+sitedomain);
		this.sitedomain = sitedomain;
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		this.sitedomain = filterConfig.getInitParameter("sitedomain");
		logger.info("[RTP]RequestTokenParameterFilter init("+sitedomain+")");
	}

	@Override
	public void destroy() {
		logger.info("[RTP]RequestTokenParameterFilter destroy");
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException {
		logger.info("[RTP][1]inside doFilter value:"+sitedomain);
		HttpServletRequest httpServletRequest = (HttpServletRequest) request;
		/* Getting actual Redirect Param Value */
		String requestURI = httpServletRequest.getRequestURI();
		//不处理的资源
		if(!isProcessed(requestURI)){
			chain.doFilter(request, response);
			return;
		}
		//若请求参数中含有token,直接退出不再增补token
		if(httpServletRequest.getParameter("token")!=null && Commons.isNotBlank(httpServletRequest.getParameter("token"))){
			chain.doFilter(request, response);
			return;
		}
		logger.info("[RTP][2]processed URI:" + requestURI);
		TokenMoldBean tmb = makeToken(httpServletRequest);
		if(!tmb.isInherit()){ //只有新生的才放到session中
			httpServletRequest.getSession().setAttribute(TS, tmb.getToken());
		}
		/*
		 * Modifying redirect param value and also adding new parameter to
		 * request object
		 */
		Map<String, String[]> modifyAddParamValueMap = new TreeMap<String, String[]>();
		String[] tokenParamArray = new String[1];
		tokenParamArray[0] = tmb.getToken();
		modifyAddParamValueMap.put(TS, tokenParamArray);
		// @20200501
		//String[] mlcParamArray = new String[1];
		//mlcParamArray[0] = tmb.getToken();
		//modifyAddParamValueMap.put("mlc", mlcParamArray);
		//
		HttpServletRequest wrappedRequest = new EnhancedHttpRequest(httpServletRequest, modifyAddParamValueMap);
		chain.doFilter(wrappedRequest, response);
	}

	// 是否是本地请求
	private boolean isLocalRequest(String httpReferer) {
		// 包含http://
		// 是否是本站地址
		if (null==sitedomain) {
			return false;
		}
		if (httpReferer.startsWith(sitedomain)) {
			return true;
		}
		return false;
	}
	//是否对资源进行处理
	private boolean isProcessed(String requestURI){
		if(requestURI.startsWith("/static")){
			return false;
		}
		//后缀也不处理
		String fe = Commons.getFileExtension(requestURI);
		if(null != fe && fe.length() > 0){
			return !Arrays.asList("js", "png", "css", "jpg", "ico", "jpeg", "svg", "html", "gif").contains(fe.toLowerCase());
		}
		return true;
	}
	private TokenMoldBean makeToken(HttpServletRequest request) {
		String token = Commons.randomAlphaNumeric(8);
		// 来源页
		String httpReferer = request.getHeader("referer");
		// 没有->
		if (null==httpReferer) {
			return new TokenMoldBean(token);
		}
		boolean isLocal = isLocalRequest(httpReferer);
		if (!isLocal) { // 来源非本站域名->
			return new TokenMoldBean(token);
		} else { // 是本站->
			// 从session|cookie中取
			Object sessionObj = request.getSession().getAttribute(TS);
			return (null==sessionObj) ? new TokenMoldBean(token) : new TokenMoldBean(sessionObj.toString(), true);
		}
	}
}
