package com.goafanti.core.shiro.cache;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheException;
import org.springframework.data.redis.core.RedisTemplate;

public class ShiroRedisCache implements Cache<String, Object> {

	public static final String				PREFIX		= "SHIRO_SESSION:";

	private RedisTemplate<String, Object>	redisTemplate;

	private String							name		= "shiro_session";

	private Set<String>						emptySet	= new HashSet<>();

	private long							expire		= -1l;

	public ShiroRedisCache() {

	}

	public ShiroRedisCache(RedisTemplate<String, Object> redisTemplate, String name) {
		this.redisTemplate = redisTemplate;
		this.name = name;
	}

	public ShiroRedisCache(RedisTemplate<String, Object> redisTemplate, String name, long expire) {
		this.redisTemplate = redisTemplate;
		this.name = name;
		this.expire = expire;
	}

	@Override
	public Object get(String key) throws CacheException {
		if (key == null) {
			return null;
		}
		return redisTemplate.opsForValue().get(decorateKey(key));
	}

	@Override

	public Object put(String key, Object value) throws CacheException {
		if (key == null || value == null) {
			return null;
		}

		redisTemplate.opsForValue().set(decorateKey(key), value, expire, TimeUnit.SECONDS);
		return value;
	}

	@Override
	public Object remove(String key) throws CacheException {
		if (key == null) {
			return null;
		}
		redisTemplate.delete(decorateKey(key));
		return Boolean.TRUE;
	}

	@Override
	public void clear() throws CacheException {
		redisTemplate.getConnectionFactory().getConnection().flushDb();
	}

	@Override
	public int size() {
		return redisTemplate.getConnectionFactory().getConnection().dbSize().intValue();
	}

	@Override
	public Set<String> keys() {
		Set<String> set = redisTemplate.keys(PREFIX + "*");
		if (set == null) {
			return emptySet;
		}
		return set;
	}

	@Override
	public Collection<Object> values() {
		return redisTemplate.opsForValue().multiGet(keys());
	}

	public RedisTemplate<String, Object> getRedisTemplate() {
		return redisTemplate;
	}

	public void setRedisTemplate(RedisTemplate<String, Object> redisTemplate) {
		this.redisTemplate = redisTemplate;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	private String decorateKey(String key) {
		return PREFIX + key;
	}
}
