package com.union.ai.api.util;

import org.apache.commons.lang3.StringUtils;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

/**
 * Created by IntelliJ IDEA.
 * Author: xingxin.jing
 * Date: 2018/11/04
 * Time: 下午5:39
 * redis 工具类      常用的方法可以写到util类中，不常用的方法使用 getJedis。Jedis 使用后需要close
 * 里边参数
 */
public class RedisUtil {

    /**
     * JedisPool.
     */
    private static JedisPool jedisPool = null;

    /**
     * 初始化JedisPool.   初始化参数可以放到base-config.properties 文件中
     */
    private static void initJedisPool() {

        Config instance = Config.getInstance();
        String redisHost = instance.getRedisHost();
        String redisPass = instance.getRedisPass();
        Integer redisPort = instance.getRedisPort();
        Integer redisMaxIdle = instance.getRedisMaxIdle();
        Integer redisMaxActive = instance.getRedisMaxActive();
        Integer redisMaxWait = instance.getRedisMaxWait();
        String redisTestOnBorrow = instance.getRedisTestOnBorrow();
        Integer database = instance.getRedisDatabase();

        // import commons-pool2-2.4.2.jar，否则The type org.apache.commons.pool2.impl.GenericObjectPoolConfig cannot be resolved.
        JedisPoolConfig config = new JedisPoolConfig();
        // 最大连接数, 默认8个,通过pool.getResource()来获取；
        // -1表示不限制；如果pool已经分配了MaxTotal个jedis实例，则此时pool的状态为exhausted(耗尽)。
        config.setMaxTotal(redisMaxActive);
        // 最大空闲(idle)连接数, 默认8个
        config.setMaxIdle(redisMaxIdle);
        // borrow(引入)一个jedis实例时，最大的等待时间，如果超过等待时间，则直接抛出JedisConnectionException，默认-1；
        config.setMaxWaitMillis(redisMaxWait);
        // 获取连接的时候检查有效性, 默认false
        config.setTestOnBorrow(Boolean.valueOf(redisTestOnBorrow));

        // redis有密码
        if (StringUtils.isNotBlank(redisPass)) {
            jedisPool = new JedisPool(config, redisHost, redisPort, 2000, redisPass, database, null);
        } else {
            // redis无密码
            jedisPool = new JedisPool(config, redisHost, redisPort, 2000, null, database, null);
        }

    }

    /**
     * 获取JedisPool实例.
     *
     * @return
     */
    public synchronized static JedisPool getPool() {
        if (null == jedisPool) {
            initJedisPool();
        }
        return jedisPool;
    }

    /**
     * 从连接池获取Jedis实例.
     *
     * @return Jedis Jedis
     * @throws Exception 异常信息
     */
    private synchronized static Jedis getJedis() throws Exception {
        Jedis jedis = null;
        try {
            jedis = getPool().getResource();
        } catch (Exception e) {
            throw new Exception("获取redis连接失败:" + e.getMessage());
        }
        return jedis;
    }

    /**
     * 向redis存入key-value,key已经存在则覆盖
     *
     * @param key   key
     * @param value value
     * @return 成功返回OK，失败返回 0
     * @throws Exception Exception
     */
    public synchronized static String set(String key, String value) throws Exception {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.set(key, value);
        } finally {
            close(jedis);
        }
    }

    /**
     * 向redis存入key-value,key已经存在则覆盖
     *
     * @param key   key
     * @param value value
     * @return 成功返回OK，失败返回 0
     * @throws Exception Exception
     */
    public synchronized static String setex(String key, int seconds, String value) throws Exception {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.setex(key, seconds, value);
        } finally {
            close(jedis);
        }
    }

    /**
     * 向redis存入key-value,并设置过期时间
     *
     * @param key    key
     * @param value  value
     * @param expire 过期时间
     * @return 成功返回OK，失败返回 0
     * @throws Exception Exception
     */
    public synchronized static String set(String key, String value, int expire) throws Exception {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            String statusCode;
            if (expire == 0) {
                statusCode = jedis.set(key, value);
            } else {
                statusCode = jedis.setex(key, expire, value);
            }
            return statusCode;
        } finally {
            close(jedis);
        }
    }

    /**
     * 取值.
     *
     * @param key 业务key
     * @return String 值
     * @throws Exception Exception
     */
    public synchronized static String get(String key) throws Exception {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.get(key);
        } finally {
            close(jedis);
        }
    }

    /**
     * 取值.
     *
     * @param key 业务key
     * @return String 值
     * @throws Exception Exception
     */
    public synchronized static Long incr(String key) throws Exception {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.incr(key);
        } finally {
            close(jedis);
        }
    }

    /**
     * 删除key.
     *
     * @param key 业务key
     * @return String 值
     * @throws Exception Exception
     */
    public synchronized static Long del(String key) throws Exception {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.del(key);
        } finally {
            close(jedis);
        }
    }

    /**
     * 批量删除key.
     *
     * @param keys 业务keys
     * @return String 值
     * @throws Exception Exception
     */
    public synchronized static Long del(String[] keys) throws Exception {
        Jedis jedis = null;
        try {
            jedis = getJedis();
            return jedis.del(keys);
        } finally {
            close(jedis);
        }
    }

    /**
     * 关闭Jedis.
     *
     * @param jedis jedis
     */
    private static void close(Jedis jedis) {
        if (null != jedis) {
            jedis.close();
        }
    }

    /**
     * 设置过期时间（过期之前可用PERSIST key删除过期时间使其一直可用；ttl key查看过期时间）
     *
     * @param key     key
     * @param seconds seconds
     * @throws Exception Exception
     */
    public static synchronized void expire(String key, int seconds) throws Exception {
        if (seconds <= 0) {
            return;
        }
        Jedis jedis = null;
        try {
            jedis = getJedis();
            jedis.expire(key, seconds);
        } finally {
            close(jedis);
        }

    }
}