package com.hys.app.framework.security;

import com.hys.app.service.system.RoleManager;
import com.hys.app.framework.cache.Cache;
import com.hys.app.model.base.CachePrefix;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.util.AntPathMatcher;

import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;

/**
 * 权限数据源提供者<br/>
 * 提供此资源需要的角色集合
 * Created by kingapex on 2018/3/27.
 *
 * @author kingapex
 * @version 1.0
 * @since 7.0.0
 * 2018/3/27
 */
public class AdminSecurityMetadataSource implements org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource {

    private final AntPathMatcher antPathMatcher = new AntPathMatcher();

    private RoleManager roleManager;

    private Cache cache;

    public AdminSecurityMetadataSource(RoleManager roleManager, Cache cache) {
        this.roleManager = roleManager;
        this.cache = cache;
    }


    @Override
    public Collection<ConfigAttribute> getAttributes(Object object) throws IllegalArgumentException {
        FilterInvocation fi = (FilterInvocation) object;
        return this.buildAttributes(fi.getRequest().getRequestURI(), fi.getRequest().getMethod());

    }


    private Collection<ConfigAttribute> buildAttributes(String url, String method) {
        List<String> roleList = new ArrayList<>();

        //从缓存中获取各个角色分别对应的菜单权限，缓存中获取不到从数据库获取，放入缓存。
        Map<String, List<String>> roleMap = (Map<String, List<String>>) cache.get(CachePrefix.ADMIN_URL_ROLE.getPrefix());
        if (roleMap == null) {
            roleMap = roleManager.getRoleMap();
        }

        if (roleMap != null) {
            for (String role : roleMap.keySet()) {
                List<String> urlList = roleMap.get(role);
                if (matchUrl(urlList, url, method)) {
                    roleList.add("ROLE_" + role);
                }
            }
        }

        if (roleList.isEmpty()) {
            //没有匹配到,默认是要超级管理员才能访问
            return SecurityConfig.createList("ROLE_SUPER_ADMIN");

        } else {
            return SecurityConfig.createList(roleList.toArray(new String[roleList.size()]));
        }

    }


    /**
     * 看一个list 中是否匹配某个url
     *
     * @param patternList 一个含有ant表达式的list
     * @param url         要匹配的Url
     * @param method      请求方式，由于改为方法级别鉴权，url可能相同，需要再根据请求方式区分
     * @return 是否有可以匹配此url的表达式, 有返回true
     */
    private boolean matchUrl(List<String> patternList, String url, String method) {
        // 遍历权限
        for (String expression : patternList) {

            // 匹配权限
            boolean isMatch = Pattern.matches(expression, url + ":" + method);

            if (isMatch) {
                return true;
            }
        }
        return false;
    }


    @Override
    public Collection<ConfigAttribute> getAllConfigAttributes() {
        return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
        return FilterInvocation.class.isAssignableFrom(clazz);
    }
}
