package com.sf.vertx.handle;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import org.springframework.data.redis.core.RedisTemplate;

import com.sf.vertx.api.pojo.Strategy;
import com.sf.vertx.constans.RedisKeyConfig;
import com.sf.vertx.service.impl.AppConfigServiceImpl;
import com.sf.vertx.utils.SpringUtils;

import cn.hutool.core.thread.ThreadUtil;
import io.vertx.ext.web.RoutingContext;
import lombok.extern.slf4j.Slf4j;

@Slf4j
public class RedisRateLimiter {
	public Map<Integer, Boolean> acquire(RoutingContext rc, Strategy strategyInterface, Strategy strategyApp) {
		String appCode = rc.request().headers().get(AppConfigServiceImpl.getSacAppHeaderKey());
		String key = null;
		Map<Integer, Boolean> retMap = new HashMap<>();
		if (strategyInterface != null) {
			key = RedisKeyConfig.APP_CURRENT_LIMITING_CONFIG_KEY + ":" + appCode + ":" + rc.request().uri() + ":"
					+ rc.request().method();
			Boolean ret = rateLimiter(key, appCode, strategyInterface.getThreshold(), strategyInterface.getTimeWindow());
			retMap.put(1, ret);
		}

		if (strategyApp != null) {
			key = RedisKeyConfig.APP_CURRENT_LIMITING_CONFIG_KEY + ":" + appCode;
			Boolean ret = rateLimiter(key, appCode, strategyApp.getThreshold(), strategyApp.getTimeWindow());
			retMap.put(2, ret);
		}
		return retMap;
	}

	@SuppressWarnings("unchecked")
	private Boolean rateLimiter(String key, String appCode, Integer threshold, Integer timeWindow) {
		RedisTemplate<String, Integer> redisTemplate = SpringUtils.getBean("redisTemplate", RedisTemplate.class);
		Object count = redisTemplate.opsForValue().get(key);
		// redisTemplate.delete(key);
		log.info("count:{}", count);
		// 初始化,设置过期时间
		ThreadUtil.execAsync(() -> {
			add(timeWindow, redisTemplate, key);
		});
		return count != null && Integer.valueOf(count.toString()) <= threshold ? true : false;
	}

	private void add(Integer timeWindow, RedisTemplate<String, Integer> redisTemplate, String key) {
		// log.info("redis app threshold: {}", redisTemplate.opsForValue().get(key));
		Long incr = redisTemplate.opsForValue().increment(key);
		if (incr == 1) { // 创建,才设置时间窗口
			redisTemplate.expire(key, timeWindow, TimeUnit.SECONDS);
		}
	}
}
