package com.lightinit.hsdataplatform.spring;

import com.lightinit.hsdataplatform.entity.SentryRoleAction;
import com.lightinit.hsdataplatform.model.admin.LoginUser;
import com.lightinit.hsdataplatform.service.IShiroPermissionsService;
import com.lightinit.hsdataplatform.service.admin.IAccountService;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.Permission;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.authz.permission.WildcardPermission;
import org.apache.shiro.cas.CasRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@SuppressWarnings("deprecation")
public class MyCasRealm extends CasRealm{

    @Autowired
    private IAccountService accountService ;

    @Autowired
    private IShiroPermissionsService shiroPermissionsService;

    /**
     * 授权访问控制，用于对用户进行的操作进行人证授权，证明该用户是否允许进行当前操作，如访问某个链接，某个资源文件等
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        String username = (String)principals.getPrimaryPrincipal();
        SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();

        // 权限控制
        Subject subject = SecurityUtils.getSubject();
        Session session = subject.getSession();
        if (session == null){
            return null;
        }
        LoginUser loginUser = (LoginUser) session.getAttribute(LoginUser.SESSION_KEY_LOGIN_USER);
        if (loginUser == null){
            return null;
        }
        /*Set<String> roles = new HashSet<String>();
        List<SentryRole> adminRoleList= roleService.QueryRoleList(username);
        boolean isSuperAdmin=false;
        for (SentryRole role:adminRoleList) {
            if(isSuperAdmin==false)
                isSuperAdmin=role.getRolecode().equalsIgnoreCase("admin");
            roles.add(role.getRolecode());
        }*/
        Set<String> roles = new HashSet<String>(loginUser.getRoles());
        boolean isSuperAdmin = roles.stream().anyMatch(q -> q.equalsIgnoreCase("admin"));
        authorizationInfo.setRoles(roles);
        Set<Permission> actions = new HashSet<Permission>();
        if(isSuperAdmin==false) {
            List<SentryRoleAction> sentryRoleActionList = shiroPermissionsService.selectSentryRoleAction(new ArrayList<String>(roles));
            for (SentryRoleAction roleModuleAction : sentryRoleActionList) {
                if (StringUtils.isEmpty(roleModuleAction.getMenucode()) || StringUtils.isEmpty(roleModuleAction.getActioncode())){
                    continue;
                }
                Permission wildcardPermission = new WildcardPermission(MessageFormat.format("{0}:{1}", roleModuleAction.getMenucode(), roleModuleAction.getActioncode()));
                if (actions.contains(wildcardPermission) == false) {
                    actions.add(wildcardPermission);
                }
            }
        }else{
            Permission wildcardPermission = new WildcardPermission("*:*");
            actions.add(wildcardPermission);
        }
        authorizationInfo.setObjectPermissions(actions);
        return authorizationInfo;
    }

    /**
     * 验证用户身份
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        AuthenticationInfo authenticationInfo = super.doGetAuthenticationInfo(token) ;
        if (token.getCredentials()!=null){
            String userName = (String) token.getPrincipal();
            SecurityUtils.getSubject().getSession().setAttribute(LoginUser.SESSION_KEY_LOGIN_USER, accountService.getLoginUserByUsername(userName));
        }
        return authenticationInfo;
    }

    @Override
    public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
        super.clearCachedAuthorizationInfo(principals);
    }

    @Override
    public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
        super.clearCachedAuthenticationInfo(principals);
    }

    @Override
    public void clearCache(PrincipalCollection principals) {
        super.clearCache(principals);
    }

    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }

    public void clearAllCachedKickoutInfo() {

    }

    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
        clearAllCachedKickoutInfo();
    }

}
