package com.publiccms.common.redis;

import java.util.HashMap;
import java.util.Map;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.publiccms.common.tools.CommonUtils;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * RedisClient
 */
public class RedisClient {
    /**
     * 
     */
    public static final int DEFAULT_EXPIRY_IN_SECONDS = 120;

    protected final Log log = LogFactory.getLog(getClass());
    private JedisPool jedisPool;
    private Map<String, RedisCacheEntity<Object, Object>> regionMap = new HashMap<>();

    /**
     * @param jedisPool
     */
    public RedisClient(JedisPool jedisPool) {
        this.jedisPool = jedisPool;
    }

    /**
     * @return
     */
    public long dbSize() {
        Jedis jedis = jedisPool.getResource();
        long size = jedis.dbSize();
        jedis.close();
        return size;
    }

    /**
     * @param region
     * @param key
     * @return
     */
    public boolean exists(String region, Object key) {
        return createOrGetCache(region).contains(key.toString());
    }

    /**
     * @param region
     * @param key
     * @return
     */
    @SuppressWarnings("unchecked")
    public <T> T get(String region, Object key) {
        T cacheItem = (T) createOrGetCache(region).get(key.toString());
        log.trace(CommonUtils.joinString("retrieve cache item. region=", region, ", key=", key, ", value=", cacheItem));
        return cacheItem;
    }

    /**
     * @param region
     * @param key
     * @param value
     */
    public void set(String region, Object key, Object value) {
        set(region, key, value, null);
    }

    /**
     * @param region
     * @param key
     * @param value
     * @param expiry
     */
    public void set(String region, Object key, Object value, Long expiry) {
        log.trace(CommonUtils.joinString("set cache item. region=", region, ", key=", key, ", timeout=",
                (CommonUtils.empty(expiry) ? 0 : expiry)));
        createOrGetCache(region).put(key.toString(), value, expiry);
    }

    /**
     * @param region
     * @param key
     * @return
     */
    public Object del(String region, Object key) {
        return createOrGetCache(region).remove(key.toString());
    }

    /**
     * @param region
     */
    public void clearRegion(String region) {
        createOrGetCache(region).clear(false);
    }

    /**
     * @param region
     */
    public void removeRegion(String region) {
        regionMap.remove(region);
    }

    /**
     * @param region
     * @return
     */
    public RedisCacheEntity<Object, Object> createOrGetCache(String region) {
        return regionMap.computeIfAbsent(region, k -> new RedisCacheEntity<>().init(k, jedisPool));
    }

    /**
     * @return
     */
    public boolean isShutdown() {
        return null != jedisPool && jedisPool.isClosed();
    }

    /**
     * 
     */
    public void shutdown() {
        if (null != jedisPool) {
            jedisPool.destroy();
        }
    }
}
