package com.elab.cache.spring.manage;

import com.alibaba.fastjson.JSON;
import com.elab.cache.ICacheClient;
import com.elab.cache.spring.wrapper.CacheValueWrapper;
import com.elab.core.utils.ObjectUtils;
import org.springframework.cache.Cache;
import org.springframework.cache.support.SimpleValueWrapper;

import java.util.Set;
import java.util.concurrent.Callable;

public class SystemCacheManage implements Cache {


    @Override
    public ValueWrapper putIfAbsent(Object key, Object value) {
        return null;
    }

    /**
     * Redis
     */
    private ICacheClient cacheClient;

    /**
     * 缓存名称
     */
    private String name;

    /**
     * 超时时间
     */
    private int timeout;

    /**
     * 暂无实现
     *
     * @param o
     * @param callable
     * @param <T>
     * @return
     */
    @Override
    public <T> T get(Object o, Callable<T> callable) {
        return null;
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.cache.Cache#getName()
     */
    @Override
    public String getName() {
        return this.name;
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.cache.Cache#getNativeCache()
     */
    @Override
    public Object getNativeCache() {
        return this.cacheClient;
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.cache.Cache#get(java.lang.Object)
     */
    @Override
    public ValueWrapper get(Object key) {
        if (ObjectUtils.isEmpty(key)) {
            return null;
        } else {
            final String finalKey;
            if (key instanceof String) {
                finalKey = (String) key;
            } else {
                finalKey = key.toString();
            }
            CacheValueWrapper wrapperObject = cacheClient.get(finalKey, CacheValueWrapper.class);
            if (wrapperObject == null) {
                return null;
            }

            Object object = null;
            if (wrapperObject.getJson() != null && wrapperObject.getClazz() != null) {
                object = JSON.parseObject(wrapperObject.getJson(), wrapperObject.getClazz());
            }
            return (object != null ? new SimpleValueWrapper(object) : null);
        }
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.cache.Cache#get(java.lang.Object, java.lang.Class)
     */
    @SuppressWarnings("unchecked")
    @Override
    public <T> T get(Object key, Class<T> type) {
        if (ObjectUtils.isEmpty(key) || null == type) {
            return null;
        } else {
            final String finalKey;
            final Class<T> finalType = type;
            if (key instanceof String) {
                finalKey = (String) key;
            } else {
                finalKey = key.toString();
            }
            final Object object = cacheClient.get(finalKey, type);
            if (finalType != null && finalType.isInstance(object) && null != object) {
                return (T) object;
            } else {
                return null;
            }
        }
    }

    /*
     * (non-Javadoc)
     * @see org.springframework.cache.Cache#put(java.lang.Object, java.lang.Object)
     */
    @Override
    public void put(final Object key, final Object value) {
        if (ObjectUtils.isEmpty(key) || ObjectUtils.isEmpty(value)) {
            return;
        } else {
            final String finalKey;
            if (key instanceof String) {
                finalKey = (String) key;
            } else {
                finalKey = key.toString();
            }
            if (!ObjectUtils.isEmpty(finalKey)) {
                String valueJson = JSON.toJSONString(value);
                CacheValueWrapper wrapper = new CacheValueWrapper(valueJson, value.getClass());
                cacheClient.set(finalKey, wrapper, timeout);
            }
        }
    }

    /*
     * 根据Key 删除缓存
     *
     * 1. 这里考虑到一些集合存在的情况,
     * 所以尽可能的情况是根据前缀去匹配key,
     * 然后将匹配到的key进行清除.
     * 所以这里还是要求在key设计的时候,有一定的规则性
     *
     */
    @Override
    public void evict(Object key) {
        if (null != key) {
            String finalKey;
            if (key instanceof String) {
                finalKey = (String) key;
            } else {
                finalKey = key.toString();
            }
            if (!com.elab.core.utils.ObjectUtils.isEmpty(finalKey)) {
                Set<String> keys = cacheClient.keys(finalKey + "*");
                for (String k : keys) {
                    cacheClient.delete(k);
                }
            }
        }
    }

    /*
     * 清除系统缓存
     */
    @Override
    public void clear() {
        System.out.println("====================");
        // TODO Auto-generated method stub
        // redisTemplate.execute(new RedisCallback<String>() {
        // public String doInRedis(RedisConnection connection) throws DataAccessException {
        // connection.flushDb();
        // return "ok";
        // }
        // });
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getTimeout() {
        return timeout;
    }

    public void setTimeout(int timeout) {
        this.timeout = timeout;
    }

    public ICacheClient getCacheClient() {
        return cacheClient;
    }

    public void setCacheClient(ICacheClient cacheClient) {
        this.cacheClient = cacheClient;
    }
}