package com.ag.redis;

import cn.hutool.core.collection.CollectionUtil;
import com.ag.util.StrUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.stereotype.Component;

import java.util.Arrays;
import java.util.List;

/**
 * RedisTemplate工具类
 * 所有与redis交互只在本类处理。
 */
@Component
public class RedisUtil {

    @Autowired
    private RedisTemplate redisTemplate;

    public void set(String key, Object obj) {
        redisTemplate.opsForValue().set(key, obj);
        //BoundValueOperations的理解对保存的值做一些细微的操作
//        BoundValueOperations boundValueOperations = redisTemplate.boundValueOps(key);
    }

    public Object get(String key) {
        //return redisTemplate.opsForValue().get(key);
        Object obj = redisTemplate.opsForValue().get(key);
        return  obj;
    }

    public boolean hasKey(String key) {
        return redisTemplate.hasKey(key);
    }

    public Object like(String dictName, String key, Integer begIndex, Integer length) {
        if (!redisTemplate.hasKey(dictName)){
            return null;
        }
        //return redisTemplate.opsForValue().get(key);
        return redisTemplate.execute(getPageScript(), CollectionUtil.newArrayList(dictName), key, begIndex, length);
    }

    /*private RedisScript<String> getLikeScript() {
        final String script = "local json = cjson.decode(redis.call('get',KEYS[1]))\n" +
                "local ret ={}\n" +
                "for i, v in ipairs(json) do\n" +
                " if(string.find(v.V,KEYS[2])) then\n" +
                "\t\ttable.insert(ret,{K=v.K,V=v.V})\n" +
                "\tend\n" +
                "end\n" +
                "return cjson.encode(ret)";
        return new DefaultRedisScript<>(script, String.class);
    }*/

    private RedisScript<String> getPageScript() {
        final String script = "local json = cjson.decode(redis.call('get',KEYS[1]))\n" +
                "local  beg = tonumber(ARGV[2])\n" +
                "local  ed = tonumber(ARGV[3]) + beg\n" +
                "local num = 0\n" +
                "local ret ={}\n" +
                "for i, v in ipairs(json) do\n" +
                "\tif(string.find(v.V,ARGV[1]) or string.find(v.K,ARGV[1])) then\n" +
                "\t\tif(num >= beg and num < ed) then\n" +
                "\t\t\ttable.insert(ret,{K=v.K,V=v.V,COMV=v.COMV,COMV2=v.COMV2})\n" +
                "\t\tend\n" +
                "\t\tnum = num + 1\n" +
                "\t\tif(num == ed) then \n" +
                "\t\t  break\n" +
                "\t\tend\n" +
                "\tend\n" +
                "end\n" +
                "return cjson.encode(ret)";
        return new DefaultRedisScript<>(script, String.class);
    }

    public Object accurateKey(String dictName, String keys) {
        if (!redisTemplate.hasKey(dictName)){
            return null;
        }
        List<String> list = Arrays.asList(keys.split(","));
        list.removeIf(str->(StrUtil.isEmpty(str)));
        if (CollectionUtil.isEmpty(list)){
            return null;
        }
        Object[] argv = new Object[list.size()];
        for (int i=0; i<list.size();i++){
            argv[i] = list.get(i).trim();
        }
        //return redisTemplate.opsForValue().get(key);
        return redisTemplate.execute(getAccurateScript(), CollectionUtil.newArrayList(dictName), argv);
    }

    private RedisScript<String> getAccurateScript() {
        final String script = "local json = cjson.decode(redis.call('get',KEYS[1]))\n" +
                "local ret ={}\n" +
                "for j=0,#ARGV,1 do\n" +
                "\tfor i, v in ipairs(json) do\n" +
                "\t\tif(v.K == ARGV[j]) then\n" +
                "\t\t\ttable.insert(ret,{K=v.K,V=v.V})\n" +
                "\t\t\tbreak\n" +
                "\t\tend\n" +
                "\tend\n" +
                "end\n" +
                "return cjson.encode(ret)";
        return new DefaultRedisScript<>(script, String.class);
    }



    public void delete(String key) {
        redisTemplate.delete(key);
    }

}
