var redis = require('redis');
var Redis = null;
var CredentialsProvider = require('../../lib/credentials/CredentialsProvider.js').CredentialsProvider;

describe('Redis', function () {
    var mock_client = null;
    
    beforeEach(function () {
        spyOn(redis, 'createClient');
        mock_client = jasmine.createSpy();
        mock_client.on = jasmine.createSpy();
        redis.createClient.andReturn(mock_client);
    });
    
    it('require', function () {
        Redis = require('../../lib/client/Redis.js').Redis;
        expect(Redis).toBeTruthy();
    });
    
    it('multiton', function () {
        var cp = new CredentialsProvider({'host': 'test'});
        var r1 = new Redis(cp);
        var r2 = new Redis(cp);
        expect(r1).toEqual(r2);
        r1.destroy();
    });
    
    it('num connections', function () {
        var cp = new CredentialsProvider({'max_connections': 2});
        var r1 = new Redis(cp);
        expect(mock_client.on).toHaveBeenCalled();
        r1.destroy();
    });
    
    it('set', function () {
        var called = null, called2 = null, cp, r1, test_key = 'a', test_val = 'b', mock_cb;
        runs(function () {
            mock_client.set = jasmine.createSpy();
            mock_client.set.andCallFake(function (key, val, cb) {
                called = true;
                cb(null, null);
            });
            cp = new CredentialsProvider({});
            r1 = new Redis(cp);
            mock_cb = jasmine.createSpy();
            mock_cb.andCallFake(function () {
                called2 = true;
            });
            r1.set(test_key, test_val, mock_cb);
        });
        
        waitsFor(function () {
            return (called != null && called2 != null);
        });
        
        runs(function () {
            expect(called).toBeTruthy();
            expect(called2).toBeTruthy();
            expect(mock_client.set).toHaveBeenCalled();
            expect(mock_client.set.mostRecentCall.args[0]).toEqual(test_key);
            expect(mock_client.set.mostRecentCall.args[1]).toEqual(test_val);
            expect(mock_cb).toHaveBeenCalledWith(null, null);
            r1.destroy();
        });
    });
    
    
    it('get', function () {
        var called = null, called2 = null, cp, r1, test_key = 'a', test_val = 'b', mock_cb;
        runs(function () {
            mock_client.get = jasmine.createSpy();
            mock_client.get.andCallFake(function (key, cb) {
                called = true;
                cb(null, test_val);
            });
            cp = new CredentialsProvider({});
            r1 = new Redis(cp);
            mock_cb = jasmine.createSpy();
            mock_cb.andCallFake(function () {
                called2 = true;
            });
            r1.get(test_key, mock_cb);
        });
        
        waitsFor(function () {
            return (called != null && called2 != null);
        });
        
        runs(function () {
            expect(called).toBeTruthy();
            expect(called2).toBeTruthy();
            expect(mock_client.get).toHaveBeenCalled();
            expect(mock_client.get.mostRecentCall.args[0]).toEqual(test_key);
            expect(mock_cb).toHaveBeenCalledWith(null, test_val);
            r1.destroy();
        });
    });
    
    it('set', function () {
        var called = null, called2 = null, mock_cb, cp, r1, test_key = 'a', test_val = 'b';
        runs(function () {
            mock_client.set = jasmine.createSpy();
            mock_client.set.andCallFake(function (key, value, cb) {
                called = true;
                cb(null, null);
            });
            cp = new CredentialsProvider({});
            r1 = new Redis(cp);
            mock_cb = jasmine.createSpy();
            mock_cb.andCallFake(function () {
                called2 = true;
            });
            r1.set(test_key, test_val, mock_cb);
        });
        
        waitsFor(function () {
            return (called != null && called2 != null);
        });
        
        runs(function () {
            expect(called).toBeTruthy();
            expect(called2).toBeTruthy();
            expect(mock_client.set).toHaveBeenCalled();
            expect(mock_client.set.mostRecentCall.args[0]).toEqual(test_key);
            expect(mock_client.set.mostRecentCall.args[1]).toEqual(test_val);
            expect(mock_cb).toHaveBeenCalledWith(null, null);
        })
    });
    
    it('hmget', function () {
        var called = null, called2 = null, mock_cb, cp, r1, test_key = 'a', test_field = 'b', test_val = 'c';
        runs(function () {
            mock_client.hmget = jasmine.createSpy();
            mock_client.hmget.andCallFake(function (key, field, cb) {
                called = true;
                cb(null, test_val);;
            });
            cp = new CredentialsProvider({});
            r1 = new Redis(cp);
            mock_cb = jasmine.createSpy();
            mock_cb.andCallFake(function () {
                called2 = true;
            });
            r1.hmget(test_key, test_field, mock_cb);
        });
        
        waitsFor(function () {
            return (called != null && called2 != null);
        });
        
        runs(function () {
            expect(called).toBeTruthy();
            expect(called2).toBeTruthy();
            expect(mock_client.hmget).toHaveBeenCalled();
            expect(mock_client.hmget.mostRecentCall.args[0]).toEqual(test_key);
            expect(mock_client.hmget.mostRecentCall.args[1]).toEqual(test_field);
            expect(mock_cb).toHaveBeenCalledWith(null, test_val);
        })
    });
    
    it('hgetall', function () {
        var called = null, called2 = null, mock_cb, cp, r1, test_key = 'a', test_val = 'c';
        runs(function () {
            mock_client.hgetall = jasmine.createSpy();
            mock_client.hgetall.andCallFake(function (key, cb) {
                called = true;
                cb(null, test_val);;
            });
            cp = new CredentialsProvider({});
            r1 = new Redis(cp);
            mock_cb = jasmine.createSpy();
            mock_cb.andCallFake(function () {
                called2 = true;
            });
            r1.hgetall(test_key, mock_cb);
        });
        
        waitsFor(function () {
            return (called != null && called2 != null);
        });
        
        runs(function () {
            expect(called).toBeTruthy();
            expect(called2).toBeTruthy();
            expect(mock_client.hgetall).toHaveBeenCalled();
            expect(mock_client.hgetall.mostRecentCall.args[0]).toEqual(test_key);
            expect(mock_cb).toHaveBeenCalledWith(null, test_val);
        })
    });
    
    it('del', function () {
        var called = null, called2 = null, test_key = 'a', cp, r1, mock_cb;
        
        runs(function () {
            mock_client.del = jasmine.createSpy();
            mock_client.del.andCallFake(function (key, cb) {
                called = true;
                cb(null, null);
            });
            cp = new CredentialsProvider({});
            r1 = new Redis(cp);
            mock_cb = jasmine.createSpy();
            mock_cb.andCallFake(function () {
                called2 = true;
            });
            r1.del(test_key, mock_cb); 
        });
        
        waitsFor(function () {
            return (called != null && called2 != null);
        });
        
        
        runs(function () {
            expect(called).toBeTruthy();
            expect(called2).toBeTruthy();
            expect(mock_client.del).toHaveBeenCalled();
            expect(mock_client.del.mostRecentCall.args[0]).toEqual(test_key);
            expect(mock_cb).toHaveBeenCalledWith(null, null);
        });
    });
});