package benjamin.groehbiel.ch.shortener.redis;

import benjamin.groehbiel.ch.JsonHelper;
import benjamin.groehbiel.ch.shortener.ShortenerHandle;
import com.fasterxml.jackson.core.JsonProcessingException;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig;

import java.io.IOException;
import java.net.URI;
import java.util.Set;

@Service
public class RedisManager {

    public static final String HASH_PREFIX = "hash:";
    public static final String COUNT_FIELD = "$count";

    private JedisPool pool;

    public RedisManager() {
        JedisPoolConfig jedisPoolConfig = new JedisPoolConfig();
        jedisPoolConfig.setMaxTotal(16);
        pool = new JedisPool(jedisPoolConfig, System.getProperty("redis.host"), Integer.parseInt(System.getProperty("redis.port")));
    }

    public String getHashFor(String key) {
        try (Jedis jedis = pool.getResource()) {
            return jedis.get(key);
        } catch (Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    public void setUrlAndHash(String key, String value) {
        try (Jedis jedis = pool.getResource()) {
            jedis.set(key, value);
        }
    }

    public ShortenerHandle getHandleFor(String hash) throws IOException {
        hash = hash.replace(HASH_PREFIX, "");

        try (Jedis jedis = pool.getResource()) {
            String json = jedis.get(HASH_PREFIX + hash);
            return JsonHelper.unserialize(json);
        }

    }

    public void storeHash(ShortenerHandle shortenerHandle) throws JsonProcessingException {
        URI url = shortenerHandle.getOriginalURI();
        setHashAndHandle(shortenerHandle.getHash(), shortenerHandle);
        setUrlAndHash(url.toString(), shortenerHandle.getHash());
        incrementByOne(COUNT_FIELD);
    }

    public void setHashAndHandle(String hash, ShortenerHandle value) throws JsonProcessingException {
        try (Jedis jedis = pool.getResource()) {
            jedis.set(HASH_PREFIX + hash, JsonHelper.serialize(value));
        }
    }

    public Set<String> getHashes() {
        return getValuesFor(HASH_PREFIX + "*");
    }

    public Long incrementByOne(String key) {
        try (Jedis jedis = pool.getResource()) {
            return jedis.incrBy(key, 1);
        }
    }

    public Long getHashCount() {
        try (Jedis jedis = pool.getResource()) {
            String shortenedSoFar = jedis.get(COUNT_FIELD);

            if (shortenedSoFar == null) {
                return 0L;
            } else {
                return Long.parseLong(shortenedSoFar);
            }
        }
    }

    private Set<String> getValuesFor(String regex) {
        try (Jedis jedis = pool.getResource()) {
            return jedis.keys(regex);
        }
    }

    public void clear() {
        try (Jedis jedis = pool.getResource()) {
            jedis.flushAll();
        }
    }

    public void close() {
        pool.destroy();
    }

    public void removeHash(String hashToDelete) throws IOException {
        ShortenerHandle hashHandle = getHandleFor(hashToDelete);
        URI originalURI = hashHandle.getOriginalURI();

        try (Jedis jedis = pool.getResource()) {
            jedis.del(HASH_PREFIX + hashToDelete);
            jedis.del(originalURI.toString());
            jedis.decrBy(COUNT_FIELD, 1);
        }
    }
}

@@ -744,16 +744,83 @@
 al(16);%0A
+%0A        if (System.getProperty(%22redis.password%22).isEmpty()) %7B%0A    
         
@@ -826,20 +826,22 @@
  pool = 
-new 
+create
 JedisPoo
@@ -841,16 +841,26 @@
 edisPool
+ForTestEnv
 (jedisPo
@@ -871,96 +871,100 @@
 nfig
-, System.getProperty(%22redis.host%22), Integer.parseInt(System.getProperty(%22redis.port%22)));
+);%0A        %7D else %7B%0A            pool = createJedisPoolForProdEnv(jedisPoolConfig);%0A        %7D
 %0A   
@@ -3066,65 +3066,8 @@
  %7D%0A%0A
-    public void close() %7B%0A        pool.destroy();%0A    %7D%0A%0A
     
@@ -3123,32 +3123,32 @@
 s IOException %7B%0A
+
         Shortene
@@ -3451,16 +3451,507 @@
       %7D%0A
-
     %7D%0A
+%0A    private JedisPool createJedisPoolForProdEnv(JedisPoolConfig jedisPoolConfig) %7B%0A        return new JedisPool(jedisPoolConfig, System.getProperty(%22redis.host%22), Integer.parseInt(System.getProperty(%22redis.port%22)), 2000, System.getProperty(%22redis.password%22));%0A    %7D%0A%0A    private JedisPool createJedisPoolForTestEnv(JedisPoolConfig jedisPoolConfig) %7B%0A        return new JedisPool(jedisPoolConfig, System.getProperty(%22redis.host%22), Integer.parseInt(System.getProperty(%22redis.port%22)));%0A    %7D%0A%0A
 %7D%0A

Fix redis authentication issue in prod