package com.crm.rely.backend.service;

import com.crm.rely.backend.core.entity.login.InfoEntity;
import com.crm.rely.backend.exception.ServiceException;

import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.List;

/**
 * @author houn
 */
public interface RedisService {
    /**
     * 无过期时间 保存转化为json 获取使用getEntity
     *
     * @param key
     * @param t
     * @param <T>
     * @return 是否移除成功
     * @throws ServiceException
     */
    <T> boolean save(String key, T t) throws ServiceException;

    /**
     * 保存转化为json 获取使用getEntity
     *
     * @param key
     * @param t
     * @param time
     * @param <T>
     * @return 是否移除成功
     * @throws ServiceException
     */
    <T> boolean save(String key, T t, long time) throws ServiceException;

    /**
     * 保存对象 使用getObject获取
     *
     * @param key
     * @param t
     * @param <T>
     * @return 是否移除成功
     * @throws ServiceException
     */
    <T> boolean saveObject(String key, T t) throws ServiceException;

    /**
     * 保存对象 使用getObject获取
     *
     * @param key
     * @param t
     * @param time
     * @param <T>
     * @return 是否移除成功
     * @throws ServiceException
     */
    <T> boolean saveObject(String key, T t, long time) throws ServiceException;

    /**
     * 获取对象 自动根据类型转化
     *
     * @param key
     * @param <T>
     * @return
     * @throws ServiceException
     */
    <T> T getObject(String key) throws ServiceException;

    /**
     * 判断key是否存在
     *
     * @param key
     * @return 标识是否存在
     * @throws ServiceException
     */
    boolean hasKey(String key) throws ServiceException;

    /**
     * 获取对戏 根据clazz转化对象类型
     *
     * @param key   key
     * @param clazz 对象的clazz
     * @param <T>
     * @return 返回得到的对象
     * @throws ServiceException
     */
    <T> T getEntity(String key, Class<T> clazz) throws ServiceException;

    /**
     * 获取对戏列表 如果春进去的是一个数组或者list使用这个获取
     *
     * @param key
     * @param clazz
     * @param <T>
     * @return
     * @throws ServiceException
     */
    <T> List<T> getList(String key, Class<T> clazz) throws ServiceException;

    /**
     * 移除key对应的键值对
     *
     * @param key
     * @return 是否移除成功
     * @throws ServiceException
     */
    boolean remove(String key) throws ServiceException;

    boolean remove(String... keys) throws ServiceException;

    boolean remove(Collection<String> keys) throws ServiceException;

    /**
     * 获取字符串 使用saveObject存储字符串时可以直接用此方法获取 如果使用save 那在获取的字符串是json格式 之后通过json在转化一下才能使用
     *
     * @param key
     * @return
     * @throws ServiceException
     */
    String getString(String key) throws ServiceException;

    /**
     * 标识redis是否成功
     *
     * @return true 成功 false 失败
     * @throws ServiceException
     */
    boolean isConnect() throws ServiceException;

    /**
     * 非阻塞锁
     * 默认设置加锁时间1000*10ms
     * 阻塞 如果获取锁失败啧休眠100ms 再次获取 非阻塞 获取锁失败则返回失败
     *
     * @param key
     * @param request
     * @return
     */
    boolean tryLock(String key, String request);

    /**
     * 阻塞锁
     * 默认设置加锁时间1000*10ms
     * 不设置阻塞时间 一直尝试获取 尽量设置阻塞时间
     * 阻塞 如果获取锁失败啧休眠100ms 再次获取 非阻塞 获取锁失败则返回失败
     *
     * @param key
     * @param request
     * @return
     * @throws InterruptedException
     */
    boolean lock(String key, String request) throws InterruptedException;

    /**
     * 锁阻塞锁
     * 默认设置加锁时间1000*10ms
     * 设置阻塞时间 如果达到阻塞时间还未获取锁 标识失败
     * 阻塞 如果获取锁失败啧休眠100ms 再次获取 非阻塞 获取锁失败则返回失败
     *
     * @param key
     * @param request
     * @param blockTime
     * @return
     * @throws InterruptedException
     */
    boolean lock(String key, String request, int blockTime) throws InterruptedException;

    /**
     * 非阻塞锁
     * 默认设置加锁时间1000*10ms
     * 阻塞 如果获取锁失败啧休眠100ms 再次获取 非阻塞 获取锁失败则返回失败
     *
     * @param key
     * @param request
     * @param expireTime 加锁时间
     * @return
     */
    boolean tryLock(String key, String request, int expireTime);

    boolean tryLock(String key, Runnable statement);

    void tryLock(String key, Runnable statement, String exceptionMsg) throws ServiceException;

    void tryLock(InfoEntity infoEntity, HttpServletRequest httpServletRequest, Runnable statement, String exceptionMsg) throws ServiceException;

    /**
     * 解锁 为了实现原子性 需要利用lua去操作
     * lua脚本放在lua/lock.lua中 名字已默认 代码中相对应 不要修改
     *
     * @param key
     * @param request
     * @return
     */
    boolean unlock(String key, String request);

    /**
     * 保存list
     *
     * @param key
     * @param list
     * @param <T>
     * @throws Exception
     */
    <T> void saveList(String key, List<T> list) throws Exception;
}
