package cclotus.weixin.gateway.service.impl;

import java.util.Calendar;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

import cclotus.weixin.gateway.WeixinConfigure;
import cclotus.weixin.gateway.service.CacheService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;

@Service
public class CacheServiceImpl implements CacheService {
	// inject the actual template
    @Autowired
    private RedisTemplate<String, String> template;
    
    private final static Map<String, Token> memCache = new ConcurrentHashMap<>();
    
    //@Autowired
    private final WeixinConfigure config;

    @Autowired
    public CacheServiceImpl(WeixinConfigure config){
    	this.config = config;
    }

    @Override
	public String getCache(String key) {
		if(config.isUseRedis()){
			return template.opsForValue().get(key);
		}else{
			Token t = memCache.get(key);
			if(t != null && t.expire >= Calendar.getInstance().getTimeInMillis())
				return t.token;
			if(t != null)
				memCache.remove(key);
			return null;
		}
	}

    @Override
	public void setCache(String key, String val) {
    	setCache(key, val, 0);
	}

    @Override
	public void setCache(String key, String val, long expire) {
		if(config.isUseRedis()){
			if (val == null) {
				template.delete(key);
				return;
			}
			if(expire > 0){
				template.opsForValue().set(key, val, expire, TimeUnit.SECONDS);
			} else {
				template.opsForValue().set(key, val);
			}
		}else{
			if (val == null) {
				memCache.remove(key);
				return;
			}
			if(expire <= 0)
				expire = Integer.MAX_VALUE;
			else
				expire = expire*1000;
			Token t = new Token(key, val, Calendar.getInstance().getTimeInMillis() + expire);
			memCache.put(key, t);
		}
	}

	public static class Token{
		String appid;
		String token;
		long expire;
		
		Token(String appid, String token, long expire){
			this.appid = appid;
			this.token = token;
			this.expire = expire;
		}
	}

}
