package com.dcit.authority.shiro.filter;

import java.util.*;

import javax.servlet.Filter;

import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.filter.mgt.DefaultFilterChainManager;
import org.apache.shiro.web.servlet.AbstractShiroFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Component;

import com.dcit.authority.config.JwtConfig;
import com.dcit.authority.shiro.config.RestPathMatchingFilterChainResolver;
import com.dcit.authority.shiro.domain.RolePermRule;
import com.dcit.authority.shiro.provider.ShiroFilterRulesProvider;
import com.dcit.common.utils.SpringContextHolder;

import lombok.extern.slf4j.Slf4j;

/**
* <p>Title: ShiroFilterChainManager</p>
* <p>Description: </p>
* <p>Company: SJZ DC-IT co. LTD</p> 
* @author ZZZ
* @date 2018年9月6日 下午10:18:53
*/
@Component
@Slf4j
public class ShiroFilterChainManager {
	
	private ShiroFilterRulesProvider shiroFilterRulesProvider;
	
	private JwtConfig jwtConfig;
	
	private StringRedisTemplate stringRedisTemplate;
	
	/**
	 * @param authRolesService
	 * @param jwtConfig
	 */
	@Autowired
	public ShiroFilterChainManager(ShiroFilterRulesProvider shiroFilterRulesProvider, JwtConfig jwtConfig, StringRedisTemplate stringRedisTemplate) {
		super();
		this.shiroFilterRulesProvider = shiroFilterRulesProvider;
		this.jwtConfig = jwtConfig;
		this.stringRedisTemplate = stringRedisTemplate;
	}

	// 初始化获取过滤链
    public Map<String,Filter> initFilters() {
        Map<String,Filter> filters = new LinkedHashMap<>();
        PasswordFilter passwordFilter = new PasswordFilter();
        filters.put("auth",passwordFilter);
        JwtFilter jwtFilter = new JwtFilter();
        jwtFilter.setJwtConfig(jwtConfig);
        jwtFilter.setRedisTemplate(stringRedisTemplate);
        filters.put("jwt",jwtFilter);
        return filters;
    }
    
    // 初始化获取过滤链规则
    public Map<String,String> initFilterChain() {
        Map<String,String> filterChain = new LinkedHashMap<>();
        // -------------anon 默认过滤器忽略的URL
        List<String> defalutAnon = Arrays.asList("/css/**","/js/**","/static/**","/ioc/eventInfo/addOrEditEventInfo","/eventInfo/addOrEditEventInfo");
        defalutAnon.forEach(ignored -> filterChain.put(ignored,"anon"));
        // -------------auth 默认需要认证过滤器的URL 走auth--PasswordFilter
        List<String> defalutAuth = Arrays.asList("/account/**");
        defalutAuth.forEach(auth -> filterChain.put(auth,"auth"));
        // -------------dynamic 动态URL
        List<RolePermRule> rolePermRules = shiroFilterRulesProvider.loadRolePermRules();
        if (null != rolePermRules) {
            rolePermRules.forEach(rule -> {
                StringBuilder Chain = rule.toFilterChain();
                if (null != Chain) {
                    filterChain.putIfAbsent(rule.getUrl(),Chain.toString());
                }
            });
        }
        
        //filterChain.put("/**","authc");
        
        return filterChain;
    }
    
    // 动态重新加载过滤链规则
    public void reloadFilterChain() {
            ShiroFilterFactoryBean shiroFilterFactoryBean = SpringContextHolder.getBean(ShiroFilterFactoryBean.class);
            AbstractShiroFilter abstractShiroFilter = null;
            try {
                abstractShiroFilter = (AbstractShiroFilter)shiroFilterFactoryBean.getObject();
                RestPathMatchingFilterChainResolver filterChainResolver = (RestPathMatchingFilterChainResolver)abstractShiroFilter.getFilterChainResolver();
                DefaultFilterChainManager filterChainManager = (DefaultFilterChainManager)filterChainResolver.getFilterChainManager();
                filterChainManager.getFilterChains().clear();
                shiroFilterFactoryBean.getFilterChainDefinitionMap().clear();
                shiroFilterFactoryBean.setFilterChainDefinitionMap(this.initFilterChain());
                shiroFilterFactoryBean.getFilterChainDefinitionMap().forEach((k,v) -> filterChainManager.createChain(k,v));
            }catch (Exception e) {
                log.error("【加载过滤链规则】异常，{}",e.getMessage());
            }
    }
	

}
