package com.goafanti.core.shiro.token;

import java.util.UUID;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;

import com.goafanti.common.constant.AFTConstants;
import com.goafanti.common.model.Admin;
import com.goafanti.common.model.AftUser;
import com.goafanti.common.model.User;
import com.goafanti.common.utils.SpringContextUtils;

public class TokenManager {
	private static final String		CSRF_TOKEN	= "CSRF_TOKEN";
	// 用户登录管理
	public static final UserRealm	realm		= SpringContextUtils.getBean("userRealm", UserRealm.class);

	/**
	 * 获取当前登录的用户User对象
	 * 
	 * @return
	 */
	public static AftUser getToken() {
		return (AftUser) SecurityUtils.getSubject().getPrincipal();
	}

	/**
	 * 获取当前登录的用户User对象Role
	 * 
	 * @return
	 */
	public static boolean hasRole(String role) {
		return SecurityUtils.getSubject().hasRole(role);
	}

	/**
	 * 获取当前登录的用户User对象Permission
	 * 
	 * @return
	 */
	public static boolean hasPermission(String permission) {
		return SecurityUtils.getSubject().isPermitted(permission);
	}

	/**
	 * 获取当前用户的Session
	 * 
	 * @return
	 */
	public static Session getSession() {
		return SecurityUtils.getSubject().getSession();
	}

	/**
	 * 获取当前用户ID
	 * 
	 * @return
	 */
	public static String getUserId() {
		return getToken() == null ? null : getToken().getId();
	}

	/**
	 * 获取当前用户WebSocketID
	 * 
	 * @return
	 */
	public static String getWebSocketKey() {
		return (String) TokenManager.getSession().getId() + "|" + getUserId();
	}

	/**
	 * 把值放入到当前登录用户的Session里
	 * 
	 * @param key
	 * @param value
	 */
	public static void setVal2Session(Object key, Object value) {
		getSession().setAttribute(key, value);
	}

	/**
	 * 从当前登录用户的Session里取值
	 * 
	 * @param key
	 * @return
	 */
	public static Object getVal2Session(Object key) {
		return getSession().getAttribute(key);
	}

	/**
	 * 获取当前登录的普通用户对象
	 * 
	 * @return
	 */
	public static User getUserToken() {
		AftUser u = getToken();
		if (u instanceof User) {
			return (User) u;
		} else {
			return null;
		}
	}

	/**
	 * 获取当前登录的管理员对象
	 * 
	 * @return
	 */
	public static Admin getAdminToken() {
		AftUser u = getToken();
		if (u instanceof Admin) {
			return (Admin) u;
		} else {
			return null;
		}
	}

	/**
	 * 获取当前管理员ID
	 * 
	 * @return
	 */
	public static String getAdminId() {
		return getToken() == null ? null : getToken().getId();
	}

	/**
	 * 
	 * 获取当前管理员所在省份
	 * 
	 * @return
	 */
	/*
	 * public static Integer getProvince() { return getToken() == null ? null :
	 * getToken().getProvince(); }
	 */

	/**
	 * 获取验证码，获取一次后删除
	 * 
	 * @return
	 */
	public static String getYZM() {
		String code = (String) getSession().getAttribute("CODE");
		getSession().removeAttribute("CODE");
		return code;
	}

	/**
	 * 获取CSRF TOKEN
	 * 
	 * @return
	 */
	public static String getCSRF() {
		return (String) getSession().getAttribute(CSRF_TOKEN);
	}

	/**
	 * 用户登录
	 * 
	 * @param user
	 * @param rememberMe
	 * @return
	 */
	public static User login(User user, Boolean rememberMe) {
		ShiroToken token = new ShiroToken(user.getUsername(), user.getPassword(), user.getType(),AFTConstants.USER_SOURCE_REGISTER);
		token.setRememberMe(null == rememberMe ? false : rememberMe);
		SecurityUtils.getSubject().login(token);
		setVal2Session(CSRF_TOKEN, UUID.randomUUID().toString().replace("-", ""));
		return (User) getToken();
	}

	/**
	 * 管理员登录
	 * 
	 * @param admin
	 * @param rememberMe
	 * @return
	 */
	public static Admin manageLogin(Admin admin, Boolean rememberMe) {
		ShiroToken token = new ShiroToken(admin.getMobile(), admin.getPassword());
		token.setRememberMe(null == rememberMe ? false : rememberMe);
		SecurityUtils.getSubject().login(token);
		return getAdminToken();
	}

	/**
	 * 判断是否登录
	 * 
	 * @return
	 */
	public static boolean isLogin() {
		return null != SecurityUtils.getSubject().getPrincipal();
	}

	/**
	 * 退出登录
	 */
	public static void logout() {
		SecurityUtils.getSubject().logout();
	}

	/**
	 * 清空当前用户权限信息。 目的：为了在判断权限的时候，再次会再次
	 * <code>doGetAuthorizationInfo(...)  </code>方法。 ps： 当然你可以手动调用
	 * <code> doGetAuthorizationInfo(...)  </code>方法。
	 * 这里只是说明下这个逻辑，当你清空了权限，<code> doGetAuthorizationInfo(...)  </code>就会被再次调用。
	 */
	public static void clearNowUserAuth() {
		realm.clearCachedAuthorizationInfo();
	}

	/**
	 * 根据UserIds 清空权限信息。
	 * 
	 * @param id
	 *            用户ID
	 */
	public static void clearUserAuthByUserId(String... userIds) {
		realm.clearCachedAuthorizationInfo(userIds);
	}
	
	/**
	 * 获取UserType
	 */
	public static Integer getUserType() {
		return getToken().getType();
	}

}
