import * as Redis from 'redis'

const {promisify} = require("util");


/**
 * Redis客户端操作封装
 * @author wufl2019@qq.com
 * @date 2020-06-23
 * @doc https://github.com/NodeRedis/node-redis
 */
export class RedisClient {

    private client: Redis;
    private getFun: Function
    private setFun: Function
    private delFun: Function
    private existsFun: Function
    private expireFun: Function
    private ttlFun: Function

    /**
     * 创建Redis客户端
     * @param host 127.0.0.1
     * @param port  6379
     * @param password 可选
     * @param database 可选 默认0
     */
    constructor(host: string, port: number, password: string = '', database: number = 0) {
        const options = {
            host: host,
            port: port,
            no_ready_check: true
        };
        this.client = Redis.createClient(options);
        if (password && password !== "") {
            this.client.auth(password, function () {
            });
        }
        if (database && database > 0) {
            this.client.select(database, function (err, data) {
                if (err) {
                    console.log("redis select db error: %s", err);
                }
            });
        }
        this.client.on("error", function (err) {
            console.log("redis[%s:%s/][db:%s][pwd:%s]连接失败: %s", host, port, database, password, err);
        });
        this.client.on("connect", function () {
            console.log("redis[%s:%s]连接成功!", host, port);
        });

        //当前版本Redis不支持promise，用 util.promisify 转换
        this.getFun = promisify(this.client.get).bind(this.client);
        this.setFun = promisify(this.client.set).bind(this.client);
        this.delFun = promisify(this.client.del).bind(this.client);
        this.existsFun = promisify(this.client.exists).bind(this.client);
        this.expireFun = promisify(this.client.expire).bind(this.client);
        this.ttlFun = promisify(this.client.ttl).bind(this.client);
    }

    /**
     * SET
     * @param key key
     * @param value value
     * @param expires 过期时间(秒),可选参数，默认不过期
     */
    async set(key: string, value: string, expires: number = 0) {
        if (expires > 0) {
            return await this.setFun(key, value, "EX", expires);
        } else {
            return await this.setFun(key, value);
        }
    }

    /**
     * 获取
     * @param key key
     */
    async get(key: string) {
        return await this.getFun(key);
    }


    /**
     * 删除
     * @param key key
     */
    async delete(key: string): Promise<boolean> {
        return await this.delFun(key) === 1;
    }

    /**
     * 判断Key是否存在
     * @param key key
     */
    async exists(key: string): Promise<boolean> {
        return await this.existsFun(key) === 1;
    }


    /**
     * 设置过期时间
     * @param key key
     * @param expires 过期时间(秒)
     */
    async expire(key: string, expires: number): Promise<boolean> {
        return await this.expireFun(key, expires) === 1;
    }

    /**
     * 设置过期时间
     * @param key key
     * @param expires 过期时间(秒)
     */
    async ttl(key: string): Promise<number> {
        return await this.ttlFun(key);
    }
}
