package com.iamberry.wechat.filters;

import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.util.Date;
import java.util.List;

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.annotation.WebFilter;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import com.iamberry.wechat.core.entity.AdminUtils;
import com.iamberry.wechat.core.entity.admin.AdminChildInfo;
import com.iamberry.wechat.core.entity.admin.AdminChildPermissionErmissions;
import com.iamberry.wechat.core.entity.admin.AdminInfo;
import com.iamberry.wechat.core.entity.admin.AdminLog;
import com.iamberry.wechat.face.admin.AdminLogService;
import com.iamberry.wechat.tools.NameUtils;
/**
 * @company	深圳爱贝源科技有限公司
 * @website www.iamberry.com
 * @author 	献
 * @tel		18271840547
 * @date	2016年10月18日
 * @explain	管理员登陆过滤器，未登陆时不能访问/main/*、/admin/*中资源; <br>
 * 			注意：绝对不允许添加/admin/*或者admin/**此类的权限路径，"admin/**"是绝对不允许的
 */
@WebFilter(value = { "/main/*", "/admin/*" })
public class AdminLoginFilter implements Filter {
	
	private static final String ERROR_PAGE = "/WEB-INF/views/admin/msg/error.jsp";

	public AdminLoginFilter() {
	}

	public void destroy() {}

	@SuppressWarnings("unchecked")
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
		
		// 权限拦截类
		HttpServletRequest req = (HttpServletRequest) request;
		HttpServletResponse resp = (HttpServletResponse) response;
		
		// 当前路径，相对于应用路径，不包括参数
		String url = req.getRequestURI().replace(req.getContextPath(), "");
		if (url.indexOf("?") != -1) {
			url = url.substring(0,  url.indexOf("?"));
		}
		// 防止盗链:一旦请求后台的数据，一定要经过判断，就算只是基本防范
		String referer = req.getHeader("referer");
		if (StringUtils.isEmpty(referer) || 
				(!(referer.startsWith("http://localhost") || referer.startsWith(NameUtils.IMAGE_BASE_URL) || referer.startsWith(NameUtils.PATH_ROOT_LCOAL)  ))) {
			setRequestDispatcherInfo(req, resp);return;
		}

		// 获取登陆用户
		Object object = AdminUtils.getLoginAdminUser(req.getSession());
		// 权限判断
		if (object == null) {
			// 未登陆用户，转向登陆页面
			resp.sendRedirect(req.getContextPath() + "/loginUI");
			return;
		}
		
		// 登陆用户，需要判断权限
		if (object instanceof AdminInfo) {
			// 进行日志记录
			chain.doFilter(req, resp);
			return;
		} else if (object instanceof AdminChildInfo) {
			// 检测数据
			List<AdminChildPermissionErmissions> list = (List<AdminChildPermissionErmissions>) req.getSession().getAttribute("permission");
			boolean flag = false;
			if (list != null && list.size() >= 1) {
				flag = permission(url, list);
				if (flag) {
					// 进行日志记录
					long startTime = System.currentTimeMillis();
					chain.doFilter(req, resp);
					AdminLog adminLog = new AdminLog();
					// cookie,此处cookie不做保存
					adminLog.setAdminLogCookie("");
					// 时间
					adminLog.setAdminLogDate(new Date());
					adminLog.setAdminLogDesc("二级管理员访问");
					adminLog.setAdminLogGrade(2);
					adminLog.setAdminLogIp(getIpAddr(req));
					adminLog.setAdminLogMethod(req.getMethod().equalsIgnoreCase("post") ? 1 : 2);
					adminLog.setAdminLogNowPage(url);
					adminLog.setAdminLogOther("");
					adminLog.setAdminLogParentPage(referer);
					adminLog.setAdminLogStatus(resp.getStatus());
					adminLog.setAdminLogUser(((AdminChildInfo) object).getAdminId());
					adminLog.setAdminLogUseTime(((int) (System.currentTimeMillis() - startTime)));
					// 获取Spring Ioc 容器
					WebApplicationContext context = WebApplicationContextUtils.getWebApplicationContext(request.getServletContext());
					// 使用JSP获取spring中注入的Bean
					AdminLogService adminService = (AdminLogService) context.getBean("adminLogServiceImpl");
					adminService.insertOne(adminLog);
					return;
				}
			}
		}
		// 凡是到此，全部改变
		setRequestDispatcherInfo(req, resp);
	}
	

	public boolean permission(String url, List<AdminChildPermissionErmissions> list) {
		for (AdminChildPermissionErmissions adminChildPermissionErmissions : list) {
			// 否则使用下面的数据
			if (adminChildPermissionErmissions.getErmissionsUrl() != null) {

				// 权限中包括**, 表示当前*前面的/下面的所有路径允许访问
				if (adminChildPermissionErmissions.getErmissionsUrl().indexOf("**") != -1) {
					String path = adminChildPermissionErmissions.getErmissionsUrl();
					path = path.substring(0, path.indexOf("*"));
					if (url.startsWith(path)) {
						// 合法
						return true;
					}
				}

				// 权限中包括*,表示当前*前面/下面的所有的路径允许访问
				if (adminChildPermissionErmissions.getErmissionsUrl().indexOf("*") != -1) {
					String path = adminChildPermissionErmissions.getErmissionsUrl();
					path = path.substring(0, path.indexOf("*"));
					url = url.replaceAll(path, "");
					if (url.indexOf("/") == -1) {
						// 合法
						return true;
					}
				}
				if (url.equals(adminChildPermissionErmissions.getErmissionsUrl())) {
					return true;
				}
			}
		}
		
		return false;
	}

	public void setRequestDispatcherInfo(HttpServletRequest req, HttpServletResponse resp)
			throws ServletException, IOException {
		req.setAttribute("title", "对不起，您的权限不够!");
		req.setAttribute("text", "对不起，您的权限不够!请联系管理员!");
		req.getRequestDispatcher(ERROR_PAGE).forward(req, resp);
	}

	private String getIpAddr(HttpServletRequest request) {
		String ipAddress = null;
		ipAddress = request.getHeader("x-forwarded-for");
		if (ipAddress == null || ipAddress.length() == 0
				|| "unknown".equalsIgnoreCase(ipAddress)) {
			ipAddress = request.getHeader("Proxy-Client-IP");
		}
		if (ipAddress == null || ipAddress.length() == 0
				|| "unknown".equalsIgnoreCase(ipAddress)) {
			ipAddress = request.getHeader("WL-Proxy-Client-IP");
		}
		if (ipAddress == null || ipAddress.length() == 0
				|| "unknown".equalsIgnoreCase(ipAddress)) {
			ipAddress = request.getRemoteAddr();
			if (ipAddress.equals("127.0.0.1")) {
				// 根据网卡取本机配置的IP
				InetAddress inet = null;
				try {
					inet = InetAddress.getLocalHost();
				} catch (UnknownHostException e) {
					e.printStackTrace();
				}
				ipAddress = inet.getHostAddress();
			}

		}

		// 对于通过多个代理的情况，第一个IP为客户端真实IP,多个IP按照','分割
		if (ipAddress != null && ipAddress.length() > 15) {
			if (ipAddress.indexOf(",") > 0) {
				ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));
			}
		}
		return ipAddress;
	}

	public void init(FilterConfig fConfig) throws ServletException {
	}
}
