package com.njcn.shiro.session;


import com.njcn.shiro.filter.KickoutSessionFilter;
import com.njcn.sso.pojo.user.User;
import com.njcn.shiro.pojo.UserOnlineBo;
import com.njcn.sso.shiro.session.SessionStatus;
import org.apache.shiro.session.Session;
import org.apache.shiro.subject.SimplePrincipalCollection;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.*;

/**
 * 用户session管理
 */
public class UserSessionManager {

	private static final Logger logger= LoggerFactory.getLogger(UserSessionManager.class);

	//判断用户是否被T的状态
	public static final String SESSION_STATUS ="njcn-online-status";

	private UserShiroSessionRepository userShiroSessionRepository;

	/**
	 * 获取所有的有效Session用户
	 */
	public  List<UserOnlineBo> getAllUser() {
		//获取所有session
		Collection<Session> sessions = userShiroSessionRepository.getAllSessions();
		List<UserOnlineBo> list = new ArrayList<>();
		for (Session session : sessions) {
			UserOnlineBo bo = getSessionBo(session);
			if(null != bo){
				list.add(bo);
			}
		}
		return list;
	}

	/**
	 * 根据ID查询 SimplePrincipalCollection
	 * @param userIds	用户ID
	 */
	public List<SimplePrincipalCollection> getSimplePrincipalCollectionByUserId(String...userIds){
		//把userIds 转成Set，好判断
		Set<String> idset = new HashSet<>(Arrays.asList(userIds));
		//获取所有session
		Collection<Session> sessions = userShiroSessionRepository.getAllSessions();
		//定义返回
		List<SimplePrincipalCollection> list = new ArrayList<>();
		for (Session session : sessions) {
			//获取SimplePrincipalCollection
			Object obj = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
			if(null != obj && obj instanceof SimplePrincipalCollection){
				//强转
				SimplePrincipalCollection spc = (SimplePrincipalCollection)obj;
				//判断用户，匹配用户ID。
				obj = spc.getPrimaryPrincipal();
				if(null != obj && obj instanceof User){
					User user = (User)obj;
					//比较用户ID，符合即加入集合
					if(null != user && idset.contains(user.getUserIndex())){
						list.add(spc);
					}
				}
			}
		}
		return list;
	}

	/**
	 * 获取单个Session
	 * @param sessionId 指定会话ID
	 */
	public UserOnlineBo getSession(String sessionId) {
		Session session = userShiroSessionRepository.getSession(sessionId);
		UserOnlineBo bo = getSessionBo(session);
		return bo;
	}


    /**
     * 删除单个Session
     * @param sessionId 指定会话ID
     */
    public void deleteSession(String sessionId) {
        userShiroSessionRepository.deleteSession(sessionId);
    }


	private UserOnlineBo getSessionBo(Session session){
		//获取session登录信息。
		Object obj = session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
		if(null == obj){
		    //如果为空的话，将之清理干净
            String sessionId=session.getId().toString();
            deleteSession(sessionId);
			return null;
		}
		//确保是 SimplePrincipalCollection对象。
		if(obj instanceof SimplePrincipalCollection){
			SimplePrincipalCollection spc = (SimplePrincipalCollection)obj;
//			  获取用户登录的，@link Pqs9000realm.doGetAuthenticationInfo(...)方法中
//			  return new SimpleAuthenticationInfo(user,user.getPswd(), getName());的user 对象。
			obj = spc.getPrimaryPrincipal();
			if(obj instanceof User){
				//存储session + user 综合信息
                User user = (User) obj;
                if(!user.getItem().equalsIgnoreCase("sso")){
					return null;
				}
                UserOnlineBo userBo = new UserOnlineBo((User)obj);
				//最后一次和系统交互的时间
				userBo.setLastAccess(session.getLastAccessTime());
				//主机的ip地址
				userBo.setHost(session.getHost());
				//session ID
				userBo.setSessionId(session.getId().toString());
				//session最后一次与系统交互的时间
				userBo.setLastAccess(session.getLastAccessTime());
				//回话到期 ttl(ms)
				userBo.setTimeout(session.getTimeout());
				//session创建时间
				userBo.setStartTime(session.getStartTimestamp());
				//是否被T下线
				Boolean marker = (Boolean) session.getAttribute(KickoutSessionFilter.KICKOUT_STATUS);
				if (null != marker && marker) {
					userBo.setItem("被踢");
				}else{
					//是否离线
					SessionStatus sessionStatus = (SessionStatus) session.getAttribute(SESSION_STATUS);
					Boolean status = sessionStatus.isOnlineStatus();
					userBo.setSessionStatus(status);
					userBo.setItem(user.getItem());
				}
				return userBo;
			}
		}
		return null;
	}
	/**
	 * 改变Session状态
	 * @param status {true:踢出,false:激活}
	 * @param sessionIds  指定会话ID
	 */
	public Map<String, Object> changeSessionStatus(Boolean status, String sessionIds) {
		Map<String,Object> map = new HashMap<>();
		try {
			String[] sessionIdArray ;
			if( !sessionIds.contains(",")){
				sessionIdArray = new String[]{sessionIds};
			}else{
				sessionIdArray = sessionIds.split(",");
			}
			for (String id : sessionIdArray) {
				Session session = userShiroSessionRepository.getSession(id);
				session.setAttribute(SESSION_STATUS, status);
				userShiroSessionRepository.saveSession(session);
			}
			map.put("status", 200);
			map.put("sessionStatus", status?1:0);
			map.put("sessionStatusText", status?"踢出":"激活");
			map.put("sessionStatusTextTd", status?"有效":"已踢出");
		} catch (Exception e) {
			logger.error("改变Session状态错误，sessionId:"+sessionIds+",异常为："+e.toString());
			map.put("status", 500);
			map.put("message", "改变失败，有可能Session不存在，请刷新再试！");
		}
		return map;
	}

	public UserShiroSessionRepository getUserShiroSessionRepository() {
		return userShiroSessionRepository;
	}

	public void setUserShiroSessionRepository(UserShiroSessionRepository userShiroSessionRepository) {
		this.userShiroSessionRepository = userShiroSessionRepository;
	}
}
