package lingtao.net.realm;

import com.github.pagehelper.util.StringUtil;
import lingtao.net.bean.LoginLog;
import lingtao.net.bean.SysPermission;
import lingtao.net.bean.SysUser;
import lingtao.net.dao.LoginIpMapper;
import lingtao.net.dao.LoginLogMapper;
import lingtao.net.dao.SysPermissionMapper;
import lingtao.net.dao.SysUserMapper;
import lingtao.net.util.DateFormatUtils;
import lingtao.net.util.LunarCalendarUtil;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.apache.shiro.util.SimpleByteSource;
import org.springframework.beans.factory.annotation.Autowired;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.List;

public class ShiroRealm extends AuthorizingRealm {
    @Autowired
    private SysUserMapper userMapper;
    @Autowired
    private SysPermissionMapper sysPermissionMapper;
    @Autowired
    private LoginIpMapper loginIpMapper;
    @Autowired
    private LoginLogMapper loginLogMapper;
    @Autowired
    private SessionDAO sessionDAO;
    // 日期格式化
    SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

    // 授权
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
        // TODO Auto-generated method stub
        return null;
    }

    private boolean ipIsInWildCardNoCheck(String ipWildCard, String ip) {
        String[] s1 = ipWildCard.split("\\.");
        String[] s2 = ip.split("\\.");
        boolean isMatchedSeg = true;
        for (int i = 0; i < s1.length && !s1[i].equals("*"); i++) {
            if (!s1[i].equals(s2[i])) {
                isMatchedSeg = false;
                break;
            }
        }
        return isMatchedSeg;
    }

    private boolean isPassIp(String loginIp) {
        // 获取所有的授权IP
        List<String> ipList = loginIpMapper.getAllIp();
        if (loginIp == "127.0.0.1") {
            return true;
        }
        for (String agreeIp : ipList) {
            // 如果当前登录的IP在授权IP中
            if (ipIsInWildCardNoCheck(agreeIp, loginIp)) {
                return true;
            }
        }
        return false;
    }


    // 登录验证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
        UsernamePasswordToken token2 = (UsernamePasswordToken) token;
//        String username = token2.getUsername();
        SimpleAuthenticationInfo info = null;

        // 从token中取出用户名
        String username = (String) token.getPrincipal();
//		String username = "admin";
        SysUser user = userMapper.getUserByUsername(username);

        if (user != null) {
            if ("0".contentEquals(user.getUserStatus())) {
                throw new LockedAccountException("用户未激活,请联系管理员");
            }
            /** 处理账号只能在授权的IP中登录 */
            // 是否允许登录标识
            boolean agreeLogin = true;
            // 当前登录用户的IP地址
//            String loginIp = SecurityUtils.getSubject().getSession().getHost();
            String loginIp = token2.getHost();
            System.out.println("当前登录用户的IP地址:" + loginIp);
            // 登录说明
            String loginRemark = formatter.format(new Date()) + "【" + user.getRealname() + " - " + username + "】 IP:" + loginIp;
            LoginLog loginLog = new LoginLog();
            if (isPassIp(loginIp)) {
                loginRemark += "--已知IP";
                loginLog.setStatus("正常");
                agreeLogin = true;
            } else {
                loginRemark += "--未知IP";
                loginLog.setStatus("异常");
                agreeLogin = false;
            }
            if ("2".equals(user.getNeedIp())) {
                agreeLogin = true;
            }
            loginLog.setLoginTime(new Date());
            loginLog.setRemark(loginRemark);
            loginLogMapper.addLog(loginLog);

            if (!agreeLogin) {
                throw new AuthenticationException("IP受限" + loginIp);
            }

            /** 处理生日 */
            /*SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            Date birthDate = null;
            String birthDay = "";
            // 生日日期/类型不为空
            if (StringUtil.isNotEmpty(user.getBirthDay()) && StringUtil.isNotEmpty(user.getBirthType())) {
                // 如果是新历生日，直接获取生日日期
                if (user.getBirthType().equals("1")) {
                    birthDay = String.format("%tY", new Date()) + "-" + user.getBirthDay();
                } else if (user.getBirthType().equals("0")) {// 如果是农历生日
                    // 先将农历生日转换成新历;调用工具类转换，使用String.format获取年、月、日
                    int[] lunarToSolar = LunarCalendarUtil.lunarToSolar(
                            Integer.valueOf(String.format("%tY", new Date())),
                            Integer.valueOf(user.getBirthDay().split("-")[0]),
                            Integer.valueOf(user.getBirthDay().split("-")[1]), true);
                    for (int i = 0; i < 3; i++) {
                        birthDay += lunarToSolar[i] + "-";
                    }
                    birthDay = birthDay.substring(0, birthDay.length() - 1);
                }
                try {
                    birthDate = sdf.parse(birthDay);
                    // 如果当天生日，改变状态
                    if (Math.abs(DateFormatUtils.getSubtractiveDays(birthDate, new Date())) == 0) {
                        // 生日:1
                        userMapper.setIsBirthDay(1, user.getUserId());
                    }
                } catch (ParseException e) {
                    // e.printStackTrace();
                }
            }*/

            /** 处理session（将用户信息存入session） */
            // 将用户信息存入session
            SecurityUtils.getSubject().getSession().setAttribute("USER_SESSION", user);
            // 获取权限列表
            List<SysPermission> persList = sysPermissionMapper.getPersByUserId(user.getUserId());
            // 将权限list存入session
            SecurityUtils.getSubject().getSession().setAttribute("USERPERS_SESSION", persList);
            info = new SimpleAuthenticationInfo(user, user.getPassword(), new SimpleByteSource("lingtao"), getName());
            // 设置session过期时间（毫秒） ：正负都可以，为负数时表示永不超时。
            SecurityUtils.getSubject().getSession().setTimeout(1000 * 60 * 60 * 14);

            /** 处理session（账号只允许同时一人登录） */
            // shiro获取所有在线用户
            Collection<Session> sessionsCollections = sessionDAO.getActiveSessions();
            // 遍历所有的在线用户
            for (Session session : sessionsCollections) {
                // 获得session中已经登录的单个用户对象
                String loginUsername = String
                        .valueOf(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY));
                // 这里的user对象也就是当前登录的loginUsername对象，判断当前登录的用户是否已是在线用户，是的话就清除
                if (String.valueOf(user).equals(loginUsername)) {
                    // 这里就把session清除，
                    session.setTimeout(0);
                    break;
                }
            }
        }
        // 框架完成验证
        return info;
    }

}
