package com.sunxung.factoring.component.cache;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Set;

import com.alibaba.fastjson.JSON;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import com.sunxung.factoring.component.util.StringUtil;
import com.sunxung.factoring.entity.sys.Session;

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

@Component
public class RedisCache {

    private static Logger logger = LoggerFactory.getLogger(RedisCache.class);
    private final static int DEFAULT_EXPIRED_SECOND = 60 * 60;
    @Autowired
    @Qualifier("jedisPool")
    private JedisPool jedisPool;
    @Value("${redis.indexDB}")
    private int indexDB;

    private Jedis getRedis() {
        Jedis jedis = jedisPool.getResource();
        jedis.select(indexDB);
        return jedis;
    }


    /** 获取缓存 */
    public String getForString(String key) {
        Jedis jedis = getRedis();
        try {
            if (StringUtil.isNotEmpty(key)) {
                return jedis.get(key);
            }
        } catch (Exception e) {
            logger.error("Exception occur when getCached value with key=" + key, e);
        } finally {
            jedis.close();
        }
        return null;
    }

    /** 获取缓存 */
    public Object get(String key) {
        Jedis jedis = getRedis();
        try {
            if (StringUtil.isNotEmpty(key)) {
                return unserialize(jedis.get(key.getBytes()));
            }
        } catch (Exception e) {
            logger.error("Exception occur when getCached value with key=" + key, e);
        } finally {
            jedis.close();
        }
        return null;
    }

    public void updateTime(String key,int time){
        Jedis jedis = getRedis();
        try {
            jedis.expire(key,time);
        } catch (Exception e) {
            logger.error("Exception occur when getCached value with key=" + key, e);
        } finally {
            jedis.close();
        }
    }

    /** 获取缓存 */
    public Object setForHash(String key,String key2,Object value) {
        Jedis jedis = getRedis();
        try {
            jedis.hset(key,key2,JSON.toJSONString(value));
        } catch (Exception e) {
            logger.error("Exception occur when getCached value with key=" + key, e);
        } finally {
            jedis.close();
        }
        return null;
    }

    /** 获取缓存 */
    public Object getForHash(String key,String key2,Class clazz) {
        Jedis jedis = getRedis();
        try {
            String hget = jedis.hget(key, key2);
            if(StringUtil.isNotEmpty(hget)){
                Object o = JSON.parseObject(hget, clazz);
                return o;
            }
        } catch (Exception e) {
            logger.error("Exception occur when getCached value with key=" + key, e);
        } finally {
            jedis.close();
        }
        return null;
    }


    /** 获取缓存 */
    public void removeForHash(String key,String key2) {
        Jedis jedis = getRedis();
        try {
              jedis.hdel(key, key2);
        } catch (Exception e) {
            logger.error("Exception occur when getCached value with key=" + key, e);
        } finally {
            jedis.close();
        }
    }


    /**
     * 获取全部缓存session
     * 
     * @param startKey
     * @return
     */
    public List<Session> getSession(String startKey) {
        Jedis jedis = getRedis();
        try {
            List<Session> objs = new ArrayList<Session>();
            Set<String> s = jedis.keys(startKey + "*");
            Iterator<String> it = s.iterator();
            while (it.hasNext()) {
                String key = (String) it.next();
                Object value = unserialize(jedis.get(key.getBytes()));
                objs.add((Session) value);
            }
            return objs;
        } catch (Exception e) {
            logger.error("Exception occur when getCached value", e);
        } finally {
            jedis.close();
        }
        return null;
    }

    /** 获取缓存并更新缓存时间 */
    public Object getAndUpdate(String key, int expried) {
        try {
            Object value = get(key);
            if (value != null) {
                expried = expried > 0 ? expried : DEFAULT_EXPIRED_SECOND;
                set(key, expried, value);
            }
            return value;
        } catch (Exception e) {
            logger.error("Exception occur when getAndUpdateCached value with key=" + key, e);
            return null;
        }
    }

    /** 设置缓存 */
    public void set(String key, Object value) {
        set(key, DEFAULT_EXPIRED_SECOND, value);
    }

    /** 设置缓存 */
    public void setForString(String key, Object value,Integer time) {
        Jedis jedis = getRedis();
        try {
            if (value != null && StringUtil.isNotEmpty(key)) {
                if(time==null){
                    time = DEFAULT_EXPIRED_SECOND;
                }
                jedis.setex(key, time, JSON.toJSONString(value));
            }
        } catch (Exception e) {
            logger.error("Exception occur when setCached value with key=" + key + ",value=" + value, e);
        } finally {
            jedis.close();
        }
    }

    public void set(String key, int expried, Object value) {
        Jedis jedis = getRedis();
        try {
            if (value != null && StringUtil.isNotEmpty(key)) {
                jedis.setex(key.getBytes(), expried, serialize(value));
            }
        } catch (Exception e) {
            logger.error("Exception occur when setCached value with key=" + key + ",value=" + value, e);
        } finally {
            jedis.close();
        }
    }

    public void remove(String key) {
        Jedis jedis = getRedis();
        try {
            if (StringUtil.isNotEmpty(key)) {
                jedis.del(key);
            }
        } catch (Exception e) {
            logger.error("Exception occur when removeCached value with key=" + key, e);
        } finally {
            jedis.close();
        }
    }

    public Object get(String nameSpace, String key) {
        if (StringUtil.isEmpty(nameSpace) || StringUtil.isEmpty(key)) {
            return null;
        }
        return get(nameSpace + "_" + key);
    }

    public void invalidateNameSpaceCache(String nameSpace) {
        Jedis jedis = getRedis();
        try {
            if (StringUtil.isEmpty(nameSpace)) {
                return;
            }
            Set<byte[]> sets = jedis.keys((nameSpace + "*").getBytes());
            if (sets != null) {
                for (byte[] set : sets) {
                    jedis.del(set);
                }
            }
        } catch (Exception e) {
            logger.error("Exception occur when invalidateNameSpaceCached with nameSpace=" + nameSpace, e);
        } finally {
            jedis.close();
        }
    }

    /** 移除缓存 */
    public void remove(String nameSpace, String key) {
        if (StringUtil.isNotEmpty(nameSpace) && StringUtil.isNotEmpty(key)) {
            remove(nameSpace + "_" + key);
        }
    }

    public void set(String nameSpace, String key, Object value) {
        if (StringUtil.isNotEmpty(nameSpace) && StringUtil.isNotEmpty(key) && value != null) {
            set(nameSpace + "_" + key, value);
        }
    }

    public void set(String nameSpace, String key, int expried, Object value) {
        if (StringUtil.isNotEmpty(nameSpace) && StringUtil.isNotEmpty(key) && value != null) {
            set(nameSpace + "_" + key, expried, value);
        }
    }

    /** 清空缓存 */
    public void flushAll() throws Exception {
        Jedis jedis = getRedis();
        try {
            jedis.flushAll();
        } finally {
            jedis.close();
        }
    }

    /** 测试缓存服务是否可连接 */
    public boolean testConnect() {
        Jedis jedis = getRedis();
        try {
            jedis.isConnected();
            if ("PONG".equalsIgnoreCase(jedis.ping())) {
                return true;
            }
        } finally {
            jedis.close();
        }
        return false;
    }

    /** 序列化 */
    public byte[] serialize(Object object) {
        ObjectOutputStream oos = null;
        ByteArrayOutputStream baos = null;
        try {
            baos = new ByteArrayOutputStream();
            oos = new ObjectOutputStream(baos);
            oos.writeObject(object);
            byte[] bytes = baos.toByteArray();
            return bytes;
        } catch (Exception e) {
            logger.error("Exception occur when cache serialize 失败", e);
        } finally {
            if (oos != null) {
                try {
                    oos.close();
                } catch (IOException e) {
                }
            }
            if (baos != null) {
                try {
                    baos.close();
                } catch (IOException e) {
                }
            }
        }
        return null;
    }

    /** 反序列化 */
    public Object unserialize(byte[] bytes) {
        if (bytes == null) {
            return null;
        }
        ByteArrayInputStream bais = null;
        ObjectInputStream ois = null;
        try {
            bais = new ByteArrayInputStream(bytes);
            ois = new ObjectInputStream(bais);
            return ois.readObject();
        } catch (Exception e) {
            logger.error("Exception occur when cache unserialize 失败", e);
        } finally {
            if (ois != null) {
                try {
                    ois.close();
                } catch (IOException e) {
                }
            }
            if (bais != null) {
                try {
                    bais.close();
                } catch (IOException e) {
                }
            }
        }
        return null;
    }
}
