import * as Redis from 'redis';
import { promisifyAll } from 'bluebird';

// 映射 redis 接口
declare module 'redis' {
    export interface RedisClient extends NodeJS.EventEmitter {
        // key 是否存在。
        existsAsync(key: string): Promise<number>; 
        // 在 key 存在时删除 key。
        delAsync(key: string): Promise<number>; 
        // 在 key 存在时删除 key。
        keysAsync(pattern: string): Promise<string[]>; 
        // 设置过期时间
        expireAsync(key: string, time: number): Promise<number>;
        // 按时间戳设置过期时间
        expireatAsync(key: string, time: number): Promise<number>;
        // string类型存储
        setexAsync(key: string, time: number, value: string): Promise<number>;
        // 获取存储string类型value
        getAsync(key: string): Promise<string>;
         // 获取存储string类型value
        setAsync(key: string, value: string): Promise<number>;
        // 删除哈希表 key 中的一个或多个指定字段
        hdelAsync(key: string, field: string): Promise<number>;
        // 将哈希表 key 中的字段 field 的值设为 value
        hsetAsync<T>(key: string, field: string, value: T): Promise<T>;
        // 获取存储在哈希表中指定字段的值
        hgetAsync(key: string, field: string): Promise<any>;
        // 获取存储在哈希表中指定字段的值。
        hexistsAsync(key: string, field: string): Promise<number>;
        // 获取哈希表中所有字段和值
        hgetallAsync(key: string): Promise<any>;
        // 增值
        hincrbyAsync(key: string, field: string, inc: number): Promise<number>;
        // 命令返回哈希表所有的值。
        hvalsAsync(key: string): Promise<any>;
         
        // 移除并返回集合中的一个随机元素
        spopAsync(key: string, count?: number): Promise<number>;
        // 移除集合中一个或多个成员
        sremAsync(key: string, member: string): Promise<number>;
        // 返回集合中一个或多个随机数
        srandmemberAsync(key: string, count?: number): Promise<string|string[]>;
        // 判断成员元素是否是集合的成员
        sismemberAsync(key: string, member: string): Promise<boolean>;

        // 向有序集合添加一个或多个成员，或者更新已存在成员的分数
        zaddAsync(key: string, score: number, member: string): Promise<number>;
        // 返回有序集中指定分数区间内的成员，分数从高到低排序
        zrevrangebyscoreAsync(key: string, max: (string|number), min: (string|number), withscores?: string, limit?:string, offset?: number, count?:number): Promise<string[]>;
        // 返回有序集中指定分数区间内的成员，分数从高到低排序
        zrangebyscoreAsync(key: string, min: (string|number), max: (string|number), withscores?: string, limit?:string, offset?: number, count?:number): Promise<string[]>;
        // 获取有序集合的成员数
        zcardAsync(key: string): Promise<number>;
        // 移除有序集合中给定的排名区间的所有成员
        zremrangebyrankAsync(key: string, start: number, stop: number): Promise<number>;
        // 移除有序集中的一个或多个成员
        zremAsync(key: string, member: string): Promise<number>;
        // 返回有序集中指定成员的排名，从小到大
        zrankAsync(key: string, field: string): Promise<number>;
        // 返回有序集中指定成员的排名，从大到小
        zrevrankAsync(key: string, field: string): Promise<number>;
        // 命令返回有序集中，指定区间内的成员，从大到小
        zrevrangeAsync(key: string, start: number, end: number, withscores?: string): Promise<string[]>;
        // 对有序集合中指定成员的分数加上增量 increment
        zincrbyAsync(key: string, increment: number, member: string): Promise<number>;
        // 对有序集合中指定成员的分数加上增量 increment
        zunionstoreAsync(destination: string, numkeys: number, ...args: any): Promise<number>;
        // 返回有序集中，成员的分数值
        zscoreAsync(key: string, member: string): Promise<number>;
        // 显示集合成员
        smembersAsync(key: string): Promise<string[]>;
        // 增加集合成员
        saddAsync(key: string, values: string[]): Promise<string>;
         // 将信息发送到指定的频道
        publishAsync(channel: string, message: string): Promise<number>;
        // 订阅给定的一个或多个频道的信息
        subscribeAsync(...channels: string[]): Promise<number>;
        // 返回hash字段数量
        hlenAsync(key: string): Promise<number>;
        // 返回hash键
        hkeysAsync(key: string): Promise<string[]>;
    }
    export interface Multi extends Commands<Multi> {
        execAsync(...args: any[]): Promise<any>;
    }
}

export function connectRedis(redisArr: string, redisPw: string) {

    // 创建 redis 连接
    const oldRedisClient = Redis.createClient(6379, redisArr, {detect_buffers: true});
    oldRedisClient.auth(redisPw, (err, _reply) => {
        if (err) {
            console.log('redis err', err);
        } else {
            console.log('redis suc');
        }
    })

    // 转 promise
    const client = promisifyAll(oldRedisClient) as Redis.RedisClient;
    promisifyAll(Redis.Multi.prototype);
    client.set('hello', 'redis', Redis.print);

    return client;
}