import { Singleton, Container, Scope, Inject } from "typescript-ioc";
import * as Redis from 'redis'
const Redlock = require('redlock');
const { promisify } = require("util");
let commands = require('redis-commands');
import { Config } from '../config/Config'

@Singleton
export class RedisUtil {

    private redisClient;
    private redlock;
    private redisCommons = {};

    constructor() {
        const host = Config.getRedisLockHost()
        const port = Config.getRedisLockPassword()
        const password = Config.getRedisLockPassword()
        const database = Config.getRedisLockDatabase()
        this.createRedisClient(host, Number(port), password, Number(database))

        this.redlock = new Redlock([this.redisClient], {
            retryCount: 0,//重试次数
            retryDelay: 0//重试间隔
        })
    }

    private createRedisClient(host: string, port: number, password: string = '', database: number = 0) {
        const options = {
            host: host,
            port: port,
            no_ready_check: true
        };
        this.redisClient = Redis.createClient(options);
        if (password && password !== "") {
            this.redisClient.auth(password, function () {
            });
        }
        if (database && database > 0) {
            this.redisClient.select(database, function (err, data) {
                if (err) {
                    console.log("redis select db error: %s", err);
                }
            });
        }
        this.redisClient.on("error", function (err) {
            console.log("redis[%s:%s/][db:%s][pwd:%s]连接失败: %s", host, port, database, password, err);
        });
        this.redisClient.on("connect", function () {
            console.log("redis[%s:%s]连接成功!", host, port);
        });

        //当前版本Redis不支持promise，用 util.promisify 转换
        for (let command of commands.list) {
            this.redisCommons[command] = promisify(this.redisClient[command]).bind(this.redisClient);
        }

    }

    async lock(lockId: string, ms: number = 1000): Promise<any> {
        try {
            const resource = `locks:${lockId}`
            const lock = await this.redlock.lock(resource, ms)
            console.log('加锁成功------' + resource)
            return lock
        } catch (e) {
            console.log('Lock error.....' + e)
        }
    }

    async unlock(lock: any): Promise<any> {
        try {
            if (lock) {
                await this.redlock.unlock(lock)
                console.log('锁释放完成...' + lock.resource)
            }
        } catch (e) {
            console.log('UnLock error.....' + e)
        }
    }

    /**
    * 获取
    * @param key key
    */
    async get(key: string): Promise<any> {
        return await this.redisCommons['get'](key);
    }
}