package cn.md.common.shiro;

import java.util.List;
import java.util.Set;

import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.LockedAccountException;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

import cn.md.common.model.Operator;
import cn.md.common.model.Resource;
import cn.md.common.model.Role;
import cn.md.common.repository.CommonRepository;
import cn.md.common.rowmapper.OperatorRowMapper;
import cn.md.common.rowmapper.ResourceRowMapper;
import cn.md.common.rowmapper.RoleRowMapper;

import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.collect.Collections2;
import com.google.common.collect.Sets;

@SuppressWarnings("all")
public class OperatorRealm extends AuthorizingRealm {
	
	private CommonRepository commonRepository;

	public CommonRepository getCommonRepository() {
		return commonRepository;
	}

	public void setCommonRepository(CommonRepository commonRepository) {
		this.commonRepository = commonRepository;
	}

	protected AuthorizationInfo doGetAuthorizationInfo(final PrincipalCollection principals) {
		Object _primaryPrincipal = principals.getPrimaryPrincipal();
		final String username = ((String) _primaryPrincipal);
		final SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
		Operator _findByUsername =  commonRepository.findOne("t_operator", "username", username, new OperatorRowMapper());
		List<Role> _roles = commonRepository.query("select role.* from t_role role join t_operator_role rt where rt.operator_id = "+_findByUsername.getId() +";", new RoleRowMapper());
		final Function<Role, String> _function = new Function<Role, String>() {
			public String apply(final Role it) {
				return it.getName();
			}
		};

		Iterable<String> _map = Collections2.transform(_roles, _function);
		Set<String> _set = Sets.<String> newHashSet(_map);
		authorizationInfo.setRoles(_set);
		
		
		final Function<Role, Set<String>> _function_1 = new Function<Role, Set<String>>() {
			public Set<String> apply(final Role it) {
				List<Resource> _resources = commonRepository.query("select resource.* from t_resource resource join t_role_resource rr where rr.role_id = "+it.getId() +" group by resource.permission ;", new ResourceRowMapper());
				final Function<Resource, String> _function = new Function<Resource, String>() {
					public String apply(final Resource it) {
						return it.getPermission();
					}
				};
				Iterable<String> _map = Collections2.transform(_resources, _function);
				return Sets.<String> newHashSet(_map);
			}
		};
		Iterable<Set<String>> _map_1 = Collections2.transform(_roles, _function_1);
		Set<String> _reduce = Sets.newHashSet();
		for (Set<String> set : _map_1) {
			_reduce.addAll(set);
		}
		authorizationInfo.setStringPermissions(_reduce);
		return authorizationInfo;
	}

	protected AuthenticationInfo doGetAuthenticationInfo(final AuthenticationToken token)
			throws AuthenticationException {
		Object _principal = token.getPrincipal();
		final String username = ((String) _principal);
		final Operator operator =  commonRepository.findOne("t_operator", "username", username, new OperatorRowMapper());
		boolean _equals = Objects.equal(operator, null);
		if (_equals) {
			throw new UnknownAccountException();
		}
		Boolean _enable = operator.getEnable();
		boolean _equals_1 = Boolean.FALSE.equals(_enable);
		if (_equals_1) {
			throw new LockedAccountException();
		}
		String _username = operator.getUsername();
		String _password = operator.getPassword();
		byte[] _bytes = "I\'m a salt".getBytes();
		ByteSource _bytes_1 = ByteSource.Util.bytes(_bytes);
		String _name = this.getName();
		final SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(_username, _password,
				_bytes_1, _name);
		return authenticationInfo;
	}

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

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

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

	public void clearAllCachedAuthorizationInfo() {
		Cache<Object, AuthorizationInfo> _authorizationCache = this.getAuthorizationCache();
		_authorizationCache.clear();
	}

	public void clearAllCachedAuthenticationInfo() {
		Cache<Object, AuthenticationInfo> _authenticationCache = this.getAuthenticationCache();
		_authenticationCache.clear();
	}

	public void clearAllCache() {
		this.clearAllCachedAuthenticationInfo();
		this.clearAllCachedAuthorizationInfo();
	}
}