package com.games.gateway.utils;

import com.github.benmanes.caffeine.cache.Caffeine;
import com.github.benmanes.caffeine.cache.LoadingCache;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Component
@Slf4j
public class IpBlackCache implements InitializingBean {

    @Autowired
    private RedisTemplate<String, String> redisTemplate;

    private LoadingCache<String, List<String>> ipBlackLocalCache;

    @Autowired
    private RedisKeyUtils redisKeyUtils;

    /**
     * 判断ip是否是黑名单
     *
     * @param ip
     * @return
     */
    public Boolean isBlack(String ip) {
        String ipBlackKey = redisKeyUtils.ipBlackKey();
        List<String> ipBlackList = ipBlackLocalCache.get(ipBlackKey);
        return ipBlackList.contains(ip);
    }

    /**
     * ip黑名单缓存
     *
     * @param ipList
     */
    public void cache(List<String> ipList) {
        String ipBlackKey = redisKeyUtils.ipBlackKey();
        for (String ip : ipList) {
            redisTemplate.opsForSet().add(ipBlackKey, ip);
        }
        List<String> ipBlackList = getIpBlackList(ipBlackKey);
        ipBlackLocalCache.put(ipBlackKey, ipBlackList);
    }

    /**
     * 删除ip黑名单
     *
     * @param ipList
     */
    public void invalidate(List<String> ipList) {
        String tokenCsIpBlackKey = redisKeyUtils.ipBlackKey();
        //删除redis member
        redisTemplate.opsForSet().remove(tokenCsIpBlackKey, ipList.toArray());

        //删除pathList，再重新弄到本地缓存时头
        List<String> ipBlackList = getIpBlackList(tokenCsIpBlackKey);
        ipBlackLocalCache.put(tokenCsIpBlackKey, ipBlackList);
    }


    /**
     * 获取ip黑名单列表
     *
     * @param key
     * @return
     */
    public List<String> getIpBlackList(String key) {
        Set<String> members = redisTemplate.opsForSet().members(key);
        if (CollectionUtils.isEmpty(members)) {
            return Lists.newArrayList();
        } else {
            return members.stream().collect(Collectors.toList());
        }
    }

    /**
     * 初始化 JVM Cache
     */
    @Override
    public void afterPropertiesSet() {
        ipBlackLocalCache = Caffeine.newBuilder()
                .expireAfterWrite(5, TimeUnit.MINUTES)
                .maximumSize(100)
                .build(key -> {
                    if (!redisTemplate.hasKey(key)) {
                        return Lists.newArrayList();
                    }
                    return getIpBlackList(key);
                });
    }
}
