import * as redis from 'redis';
import { LogSystem, logSystem } from './log';
import { promisify } from 'util';

const REDIS_HOST = process.env.REDIS_HOST || 'swrp-redis';
const REDIS_PORT = Number(process.env.REDIS_PORT || 6379);
const REDIS_URL = process.env.REDIS_URL;

export class RedisSystem {
    client: redis.RedisClient = REDIS_URL ? redis.createClient(REDIS_URL) : redis.createClient(REDIS_PORT, REDIS_HOST);

    async init(): Promise<void> {
        this.client.on('error', this.error.bind(this));

        return new Promise((resolve) => {
            this.client.flushall((error: any) => {
                if (!error) {
                    logSystem.initLog('Redis', 'Connection Ready');
                    resolve();
                } else {
                    LogSystem.Error('Redis', 'error', 'Failed to flush', error);
                    process.exit();
                }
            });
        });
    }

    async get(key: string): Promise<string | null> {
        return promisify(this.client.get).call(this.client, key);
    }

    async hget(key: string, field: string): Promise<string> {
        return promisify(this.client.hget).call(this.client, key, field);
    }

    async hdel(key: string, field: string): Promise<number> {
        // @ts-ignore
        return promisify(this.client.hdel).call(this.client, key, field);
    }

    async hgetall(key: string): Promise<any> {
        return promisify(this.client.hgetall).call(this.client, key);
    }

    async hset(key: string, field: string, value: string): Promise<number> {
        // @ts-ignore
        return promisify(this.client.hset).call(this.client, key, field, value);
    }

    async smembers(key: string): Promise<string[]> {
        return promisify(this.client.smembers).call(this.client, key);
    }

    async sinter(keys: string[]): Promise<string[]> {
        // @ts-ignore
        return promisify(this.client.sinter).call(this.client, keys);
    }

    async sismemebr(key: string, member: string): Promise<number> {
        return promisify(this.client.sismember).call(this.client, key, member);
    }

    async scard(key: string): Promise<number> {
        return promisify(this.client.scard).call(this.client, key);
    }

    async del(key: string): Promise<number> {
        // @ts-ignore
        return promisify(this.client.del).call(this.client, key);
    }

    async sadd(key: string, member: string | string[]): Promise<number> {
        // @ts-ignore
        return promisify(this.client.sadd).call(this.client, key, member);
    }

    async srem(key: string, member: string): Promise<number> {
        // @ts-ignore
        return promisify(this.client.srem).call(this.client, key, member);
    }

    error(error: string): void {
        LogSystem.Error('Redis', 'error', error, error);
    }
}

export const redisSystem = new RedisSystem();
