describe("OpalCredentialsProvider", function () {
        var CredentialsProvider = require('../../lib/credentials/CredentialsProvider.js').CredentialsProvider;
        //required libs
		var Response = require('../../lib/net/Response.js').Response;
		var Loader = require('../../lib/net/Loader.js').Loader;
        var OpalLoader = require('../../lib/opal/OpalLoader.js').OpalLoader;
        var OpalResponse = require('../../lib/opal/OpalResponse.js').OpalResponse;
        var JsonRpcResponse = require('../../lib/jsonrpc/JsonRpcResponse.js').JsonRpcResponse;
        var ExampleCredentialClient = null;
        var Event = require('../../lib/event/Event.js').Event;    
        var MockOpalLoader;
        var OpalCredentialsProvider;
        
        //Example client
        var ExampleCredentialClient = function (credentialsProvider) {
            this.credentialsProvider = credentialsProvider;
            //this.credentialsProvider.addEventListener(CredentialsProvider.Event.LOAD, this._onCredentialsLoad, this);
            
            this._credentials = null;
        }
        ExampleCredentialClient.prototype._onCredentialsLoad = function (e) {
            this._credentials = e.data;
            //creating pool itd
        };
        ExampleCredentialClient.prototype.get = function (key, callback) {
            //getting from pool itd
            this.credentialsProvider.get(function (err, credentials) {
                if (credentials) {
                    callback(credentials);   
                } else {
                    expect(false).toBeTruthy();
                }
            });
        };
        var load = function () {};
        //Preparing mock OpalLoader
        MockOpalLoader = function () {
            return OpalLoader.call(this);
        };
        MockOpalLoader.prototype = Object.create(OpalLoader.prototype);
        MockOpalLoader.prototype.load = function () {
            
            load(this);
        };  
    beforeEach(function () {
        var mod = require('module');
        mod._cache = {};
        spyOn(require('../../lib/opal/OpalLoader.js'), 'OpalLoader').andReturn(new MockOpalLoader());
        
        OpalLoader = require('../../lib/opal/OpalLoader.js').OpalLoader;
        OpalLoader.Event = {};
        OpalLoader.Event.JSON_RESPONSE = 'OpalLoader_JSON_RESPONSE';
        OpalLoader.Event.HTTP_RESPONSE = 'OpalLoader_HTTP_RESPONSE';
        
        //require actualy tested class
        OpalCredentialsProvider = require('../../lib/opal/OpalCredentialsProvider.js').OpalCredentialsProvider; 
        expect(OpalCredentialsProvider).not.toBeNull();
    });

	it ("credentials supplier problems / retrieving error but with stale credetnials / provider usage", function () {
        
        var done = false;
        var exampleCredential = {"example":"credential"};
        load = function (that) {
            setTimeout(function () {
                var response = new OpalResponse({
                    "statusCode": 200,
                    "headers": {},
                    "httpVersion": "1.0",
                    "body": new JsonRpcResponse("test", exampleCredential)
                });
                that.dispatchEvent(new Event(OpalLoader.Event.JSON_RESPONSE, response));
            }, 1);
        };        
        var provider = new OpalCredentialsProvider(
            "include-cache.membase.edgeserver.onetapi.pl", 
            "edgeserver.edgeserver.onetapi.pl"
        );
		
		provider.get(function (err, credentials) {
			//console.log("first get",arguments);
			expect(err).toBeFalsy();
			expect(credentials).toBe(exampleCredential);
			done = true;
		});
        /*var exampleClient = new ExampleCredentialClient(provider);
        exampleClient.get("test", function (credentials) {
            
            expect(credentials).not.toBeNull();
            expect(credentials).toBe(exampleCredential);
            done = true;
        });*/
        
        waitsFor(function () {
            return done == true;
        });
        runs(function () {
			done = false;
			load = function (that) {
				setTimeout(function () {
					var response = new Response({
						"statusCode": 503,
						"headers": {},
						"httpVersion": "1.0",
						"body": ""
					});
					that.dispatchEvent(new Event(Loader.Event.ERROR, response));
				}, 1);
			};
			provider.refresh();
			provider.get(function (err, credentials) {
				//console.log("second get",arguments);
				expect(err).not.toBeFalsy();
				expect(credentials).toBe(exampleCredential);
				done = true;
			});
        });
        waitsFor(function () {
            return done == true;
        });        
        runs(function () {
            /*exampleClient.get("test", function (credentials) {
				expect(credentials).not.toBeNull();
				expect(credentials).toBe(exampleCredential);
				done = true;
			});*/
			
			provider.destroy();
        });
    });

    it ("standard provider-client usage", function () {
        
        var done = false;
        var exampleCredential = {"example":"credential"};
        load = function (that) {
            setTimeout(function () {
                var response = new OpalResponse({
                    "statusCode": 200,
                    "headers": {},
                    "httpVersion": "1.0",
                    "body": new JsonRpcResponse("test", exampleCredential)
                });
                that.dispatchEvent(new Event(OpalLoader.Event.JSON_RESPONSE, response));
            }, 1);
        };        
        var provider = new OpalCredentialsProvider(
            "include-cache.membase.edgeserver.onetapi.pl", 
            "edgeserver.edgeserver.onetapi.pl"
        );
        var exampleClient = new ExampleCredentialClient(provider);
        exampleClient.get("test", function (credentials) {
            
            expect(credentials).not.toBeNull();
            expect(credentials).toBe(exampleCredential);
            done = true;
        });
        
        waitsFor(function () {
            return done == true;
        });
        
        runs(function () {
            provider.destroy();
        });
    });
    
    it ("provider-client usage - changed credentials", function () {
        
        var done = false;
        var exampleCredentials1 = {"example":"credentials 1"};
        var exampleCredentials2 = {"example":"credentials 2"};
        
        var response1 = new OpalResponse({
            "statusCode": 200,
            "headers": {},
            "httpVersion": "1.0",
            "body": new JsonRpcResponse("test", exampleCredentials1)
        });
        
        var response2 = new OpalResponse({
            "statusCode": 200,
            "headers": {},
            "httpVersion": "1.0",
            "body": new JsonRpcResponse("test", exampleCredentials2)
        });
        
        load = function (that) {
            
            setTimeout(function () {
                that.dispatchEvent(new Event(OpalLoader.Event.JSON_RESPONSE, response1));
            }, 1);
        };  
        //MockOpalLoader.prototype.load = function () {};        
        var provider = new OpalCredentialsProvider(
            "example2", 
            "example2"
        );
        provider.refreshTime = 100;
        var exampleClient = new ExampleCredentialClient(provider);
        
        runs(function () {
            
            done = false; 
            exampleClient.get("test", function (credentials) {
                
                expect(credentials).not.toBeNull();
                expect(credentials).toBe(exampleCredentials1);
                done = true;
            });
        });
        
        waitsFor(function () {
            return done == true;
        });
        
        runs(function () {  
            
            done = false;   
            exampleClient.get("test", function (credentials) {
                expect(credentials).not.toBeNull();
                expect(credentials).toBe(exampleCredentials1);
                done = true;
            });
        });
        
        waitsFor(function () {
            return done == true;
        });
        
        runs(function () {  
            
            done = false;   
            
            load = function (that) {
                
                setTimeout(function () {
                    that.dispatchEvent(new Event(OpalLoader.Event.JSON_RESPONSE, response2));
                }, 1);
            };  
        });
        waits(200);
        
        runs(function () {  
            
            exampleClient.get("test", function (credentials) {
                expect(credentials).not.toBeNull();
                expect(credentials).toBe(exampleCredentials2);
                done = true;
            });
        });
        
        waitsFor(function () {
            return done == true;
        });
        
        runs(function () {
            provider.destroy();
        });
    });
	
});
