package com.elab.cache;

import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * 缓存接口定义
 *
 * @author Liukx
 * @create 2017-05-17 15:40
 * @email liukx@elab-plus.com
 **/
public interface ICacheClient {

    /**
     * 将一个数组key进行原子性相减
     *
     * @param key 键
     * @param num 减去的值
     * @return
     */
    Long decrby(String key, long num);

    /**
     * 将一个原子性的数值即你想那个累加
     *
     * @param key 键
     * @param num 累加的值
     * @return
     */
    Long incrby(String key, long num);

    /**
     * 判断key是否存在
     *
     * @param key
     * @return
     */
    boolean exsit(String key);

    /**
     * 设置一个键的有效时长
     *
     * @param key     键
     * @param seconds 有效时长 单位:秒
     */
    boolean expire(String key, int seconds);

    /**
     * 获取一个key的有效时长
     *
     * @param key
     * @return
     */
    Long ttl(String key);

    /**
     * 添加一个普通值
     *
     * @param key   键
     * @param value 值
     */
    <T> void set(String key, T value);

    /**
     * 添加一个list的值
     *
     * @param key  键
     * @param list 值
     */
    <T> void setList(String key, List<T> list);

    /**
     * 添加一个map的值
     *
     * @param key
     * @param map
     * @param <T>
     */
    <T> void setMap(String key, Map<String, T> map);

    /**
     * 添加一个值,并为它设置一个有效时间
     *
     * @param key       键
     * @param value     值
     * @param validTime 有效时间  1秒=1000   -1 永久有效
     */
    void set(String key, Object value, int validTime);

    /**
     * 根据键获取值
     *
     * @param key 键 - 标识
     * @return
     */
    <T> T get(String key, Class t);

    /**
     * 获取list结果集
     *
     * @param key
     * @param <T>
     * @return
     */
    <T> List<T> getList(String key, Class clazz);

    /**
     * 获取map结果集
     *
     * @param key
     * @param <T>
     * @return
     */
    <T> Map<String, T> getMap(String key, Class clazz);

    /**
     * 设置一个值到集合中,如果存在则返回key存在 则返回false
     *
     * @param key   键
     * @param value 值
     * @return
     */
    boolean setNX(String key, Object value);

    /**
     * 根据键删除一个值
     *
     * @param key 键
     */
    void delete(String key);

    /**
     * 带锁的数据操作,例如当设置一个setnx发现键已经存在,则超时时间的范围内阻塞尝试,直到锁被释放,如果过了超时时间则表示失败
     *
     * @param key     key
     * @param value   值
     * @param timeout 超时时间 单位秒
     * @return
     */
    boolean tryLock(String key, Object value, int timeout);

    /**
     * 删除带锁的数据
     *
     * @param key 带锁的key
     */
    void unLock(String key);

    /**
     * <p>通过key 和offset 从指定的位置开始将原先value替换</p>
     * <p>下标从0开始,offset表示从offset下标开始替换</p>
     * <p>如果替换的字符串长度过小则会这样</p>
     * <p>example:</p>
     * <p>value : bigsea@zto.cn</p>
     * <p>str : abc </p>
     * <P>从下标7开始替换  则结果为</p>
     * <p>RES : bigsea.abc.cn</p>
     *
     * @param key
     * @param value
     * @param offset 下标位置
     * @return 返回替换后  value 的长度
     */
    Long setRange(String key, String value, int offset);

    /**
     * <p>通过下标 和key 获取指定下标位置的 value</p>
     *
     * @param key
     * @param startOffset 开始位置 从0 开始 负数表示从右边开始截取
     * @param endOffset
     * @return 如果没有返回null
     */
    String getRange(String key, int startOffset, int endOffset);

    /**
     * <p>通过批量的key获取批量的value</p>
     *
     * @param keys string数组 也可以是一个key
     * @return 成功返回value的集合, 失败返回null的集合 ,异常返回空
     */
    List<String> mget(String... keys);

    /**
     * <p>批量的设置key:value,可以一个</p>
     * <p>example:</p>
     * <p>  obj.mset(new String[]{"key2","value1","key2","value2"})</p>
     *
     * @param keysvalues
     * @return 成功返回OK 失败 异常 返回 null
     */
    String mset(String... keysvalues);


    /**
     * <p>批量的设置key:value,可以一个,如果key已经存在则会失败,操作会回滚</p>
     * <p>example:</p>
     * <p>  obj.msetnx(new String[]{"key2","value1","key2","value2"})</p>
     *
     * @param keysvalues
     * @return 成功返回1 失败返回0
     */
    Long msetnx(String... keysvalues);

    /**
     * <p>通过key给Hash Field设置指定的值,如果key不存在,则先创建</p>
     *
     * @param key
     * @param field 字段
     * @param value
     * @return 如果存在返回0 异常返回null
     */
    Long hset(String key, String field, String value);

    /**
     * <p>Sets field in the hash stored at key to value
     * 通过key给field设置指定的值,如果key不存在则先创建,如果field已经存在,返回0</p>
     *
     * @param key
     * @param field
     * @param value
     * @return
     */
    public Long hsetnx(String key, String field, String value);

    /**
     * <p>通过key同时设置 hash的多个field</p>
     *
     * @param key
     * @param hash
     * @return 返回OK 异常返回null
     */
    public String hmset(String key, Map<String, String> hash);

    /**
     * <p>通过key 和 field 获取指定的 value</p>
     *
     * @param key
     * @param field
     * @return 没有返回null
     */
    public String hget(String key, String field);

    /**
     * <p>通过key 和 fields 获取指定的value 如果没有对应的value则返回null</p>
     *
     * @param key
     * @param fields 可以是 一个String 也可以是 String数组
     * @return
     */
    public List<String> hmget(String key, String... fields);

    /**
     * <p>通过key向list头部添加字符串</p>
     *
     * @param key
     * @param strs 可以是一个string 也可以是string数组
     * @return 返回list的value个数
     */
    Long lpush(String key, String... strs);

    /**
     * 获取指定list
     *
     * @param key        键
     * @param startIndex 开始下标
     * @param endIndex   结束下标  -1 代表获取所有
     * @return
     */
    List<String> lrange(String key, int startIndex, int endIndex);

    /**
     * 获取所有list
     *
     * @param key 键
     * @return
     */
    List<String> lrange(String key);

    /**
     * 根据key获取缓存中的数据
     *
     * @param key 缓存的key
     * @return
     */
    String get(String key);

    /**
     * 根据key的前缀获取
     *
     * @param prefixKey
     * @return
     */
    Set<String> keys(String prefixKey);
}
