package com.fos.core.filter;

import java.io.IOException;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

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

import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.context.support.WebApplicationContextUtils;
import org.springframework.web.context.support.XmlWebApplicationContext;

import com.alibaba.fastjson.JSON;
import com.fos.core.base.BaseBean;
import com.fos.core.conf.GConstants;
import com.fos.core.utils.GlobalUtil;
import com.fos.modules.frontLog.bean.FrontLogBean;
import com.fos.modules.frontLog.service.FrontLogService;

/**
 * 对请求接口进行基本信息验证类 excludedPages * .* .+ 三种均为不验证数据
 */
public class BasicVerifyFilter implements Filter {

	private String excludedPages;// 例外列表，支持正则匹配，多个地址以分号“;”分隔
	private String[] excludedPageArray;// 例外列表
	private boolean isExcludedPage = false;// 是否有例外请求链接
	private boolean isAllowAllPage = false;// 是否有例外请求链接
	private Set<String> excludedPageSet = new HashSet<String>();

	@Autowired
	private FrontLogService frontLogService;// frontlogServic注入

	@Override
	public void destroy() {
		// TODO Auto-generated method stub

	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain filterChain) throws IOException, ServletException {
		if (response instanceof HttpServletResponse) {
			HttpServletResponse rep = (HttpServletResponse) response;
			rep.setHeader("Access-Control-Allow-Origin", "*");
		}

		boolean isMultipart = ServletFileUpload
				.isMultipartContent((HttpServletRequest) request);

		HttpServletRequest req = (HttpServletRequest) request;
		
		if (isExcludedPage) {// 有例外请求链接
			String uri = req.getServletPath();
			if (excludedPageArray != null && uri != null && uri.length() != 0) {
				if (excludedPageSet.contains(uri)) {// 直接包含
					filterChain.doFilter(request, response);
					return;
				}
				for (String page : excludedPageArray) {// 遍历例外url数组
					if (uri.matches(page)) {// 在过滤url之外
						filterChain.doFilter(request, response);
						return;
					}
				}
			}
		}

		if (isMultipart == false) {// 判断enctype属性是否为multipart/form-data
			String sign = request.getParameter("sign");// .getAttribute("sign");
			String content = request.getParameter("content");
			if (StringUtils.isBlank(sign)) {

				request.setAttribute("message", "参数sign不能为NULL");
				request.getRequestDispatcher("/WEB-INF/views/errors/401.jsp")
						.forward(request, response);// 跳转到验证错误页面
				return;
			} else if (StringUtils.isBlank(content)) {

				request.setAttribute("message", "参数content不能为NULL");
				request.getRequestDispatcher("/WEB-INF/views/errors/401.jsp")
						.forward(request, response);// 跳转到验证错误页面
				return;
			}
		}

		if (isAllowAllPage) {// 所有请求通过， 不做数据验证
			filterChain.doFilter(request, response);
			return;
		}
		// 对基本数据域进行验证
		String content = request.getParameter("content");
		String sign = request.getParameter("sign");
		String message = "content及sign不允许为空";
		if (content != null && sign != null) {// 基本参数不为NULL
			BaseBean baseBean = JSON.parseObject(content, BaseBean.class);
			message = "app_code不允许为空";
			if (baseBean.getAppCode() != null) {// 基本必要参数验证通过
				message = "签名验证不匹配";
				if (GConstants.IS_VERIFY_CONTENT_SIGN == false
						|| sign.equals(GlobalUtil.getParamsSignStr(
								GConstants.SIGN_PRIVATE_KEY, content))) {// 签名验证通过
                    // 实例化
				    ServletContext sc = req.getSession().getServletContext();
			        XmlWebApplicationContext cxt = (XmlWebApplicationContext) WebApplicationContextUtils
			                .getWebApplicationContext(sc);
			        frontLogService = (FrontLogService) cxt.getBean("frontLogService");
				    // 判断是否是登录状态
				    String loginStatus = frontLogService.getLoginStatus(baseBean.getSysName());
                    if ("0".equals(loginStatus)&&(!"/api/user/loginUser".equals(req.getServletPath()))) {
                        message = "当前用户未登录";
                    } else {
	                    //更新操作时间
	                    frontLogService.changeLoginTime(baseBean.getSysName());
                        // 写入FrontLog
                        String retMsg = WriteInFrontLog(req, baseBean);
                        if (retMsg != "") {
                            request.setAttribute("message", retMsg);
                        }

                        filterChain.doFilter(request, response);
                        return;
                    }
				}
			}
		}
		request.setAttribute("message", message);
		if("当前用户未登录".equals(message)){
            request.getRequestDispatcher("/WEB-INF/views/errors/402.jsp").forward(
                    request, response);// 跳转到验证错误页面
        } else {
            request.getRequestDispatcher("/WEB-INF/views/errors/401.jsp").forward(
                    request, response);// 跳转到验证错误页面
		}
	}

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
		// TODO Auto-generated method stub
		excludedPages = filterConfig.getInitParameter("excludedPages");
		if (excludedPages != null && excludedPages.length() != 0) {
			excludedPages = excludedPages.replaceAll("\\s+|^;+|;+$", "");// 替换前后分号及所有空格
			if (excludedPages.length() != 0) {
				if (excludedPages.equals("*") || excludedPages.equals(".*")
						|| excludedPages.equals(".+")) {// 全部不验证
					isAllowAllPage = true;
				} else {
					excludedPageArray = excludedPages.split(";");
					for (int i = 0, len = excludedPageArray.length; i < len; i++) {
						excludedPageSet.add(excludedPageArray[0]);
					}
					isExcludedPage = true;
				}
			}
		}
	}
	
	/**
	 * 验证成功后，在数据库中写入FrontLog
	 */
	private String WriteInFrontLog(HttpServletRequest req, BaseBean baseBean) {

		// 获取userID
		List<String> sysUserId = frontLogService.getUserId(baseBean.getSysName());
		if (sysUserId == null || sysUserId.size() == 0) {
			String message = "该用户在系统中不存在";
			return message;
		}

		FrontLogBean frontlogbean = new FrontLogBean();
		frontlogbean.setSysUserId(sysUserId.get(0));
		frontlogbean.setUrl(req.getServletPath());
		frontlogbean.setMethod(req.getMethod());
		frontlogbean.setModuleName(baseBean.getModuleName());
		frontlogbean.setPlatform(baseBean.getPlatform());
		frontlogbean.setAppCode(baseBean.getAppCode());
		frontlogbean.setDeviceid(baseBean.getDeviceId());
		frontlogbean.setDeviceToken(baseBean.getDeviceToken());
		frontlogbean.setVersionName(baseBean.getVersion());
		frontlogbean.setLanguage(baseBean.getLanguage());

		frontLogService.addFrontLog(frontlogbean);

		return "";
	}

}
