package zmo.technology.lite.components;

import java.util.Arrays;
import java.util.Set;
import java.util.stream.Collectors;

import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolAbstract;
import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.JedisSentinelPool;
import zmo.technology.lite.application.ZeroApplication;

public class ZeroRedisComponents implements ZeroApplicationOnComplete {

    private JedisPoolConfig config;

    private JedisPoolAbstract jedisPool = null;

    public JedisPoolConfig getConfig() {

        if (config == null) {
            config = new JedisPoolConfig();
            config.setMaxTotal(ZeroApplication.getIntProperty("easydo.redis.jedis.pool.max-active"));
            config.setMaxIdle(ZeroApplication.getIntProperty("easydo.redis.jedis.pool.max-idle"));
            config.setMinIdle(ZeroApplication.getIntProperty("easydo.redis.jedis.pool.min-idle"));
            config.setMaxWaitMillis(ZeroApplication.getIntProperty("easydo.redis.jedis.pool.max-wait"));
            config.setTestOnBorrow(true);
        }

        return config;
    }

    @Override
    public void onComplete() throws Exception {
        if (jedisPool == null) {
            if (!ZeroApplication.getProperty("easydo.redis.sentinel").isEmpty()) {
                String clusterName = ZeroApplication.getProperty("easydo.redis.cluster");
                Set<String> sentinels = Arrays
                        .stream(ZeroApplication.getProperty("easydo.redis.sentinel").split(","))
                        .collect(Collectors.toSet());
                if (!ZeroApplication.getProperty("easydo.redis.password").isEmpty())
                    jedisPool = new JedisSentinelPool(clusterName, sentinels, getConfig(), 0,
                            ZeroApplication.getProperty("easydo.redis.password"));
                else
                    jedisPool = new JedisSentinelPool(clusterName, sentinels, getConfig(), 0);
            } else {
                if (!ZeroApplication.getProperty("easydo.redis.password").isEmpty())
                    jedisPool = new JedisPool(getConfig(), ZeroApplication.getProperty("easydo.redis.host"),
                            ZeroApplication.getIntProperty("easydo.redis.port"), 0,
                            ZeroApplication.getProperty("easydo.redis.password"));
                else
                    jedisPool = new JedisPool(getConfig(), ZeroApplication.getProperty("easydo.redis.host"),
                            ZeroApplication.getIntProperty("easydo.redis.port"), 0);
            }
        }
    }

    public void setConfig(JedisPoolConfig config) {
        this.config = config;
    }

    public synchronized Jedis getConnection() throws Exception {
        Jedis redis = jedisPool.getResource();
        return redis;
    }

    public void safeConnect(ZeroSafeLayer<Jedis> safeLayer) throws Exception {
        Jedis jedis = getConnection();
        try {
            safeLayer.operate(jedis);
        } catch (Exception e) {
            throw e;
        } finally {
            jedis.close();
        }
    }

    public static void safeOperate(ZeroSafeLayer<Jedis> safeLayer) throws Exception {
        ZeroApplication.getBean(ZeroRedisComponents.class).safeConnect(safeLayer);
    }
}
