(function() {
    'use strict';
    angular.module('fef',['ngResource'])
        .provider('fefLogger', FefLogProvider);
    function FefLogProvider() {
        var config = {
            consoleThreshold: 4,
            httpThreshold: 1,
            httpDomain: undefined,
            httpPath: '/demo/logs',
            delay: 250
        };
        var resource;

        var rootname = 'fef';
        var rootGuid = trmrguid();
        var $window, $location;

        function setInit(_window, _location) {
            $window = _window;
            $location = _location;
        }
        function formatError(arg, name) {
            if (arg instanceof Error) {
                if (arg.stack) {
                    arg = (arg.message && arg.stack.indexOf(arg.message) === -1) ? 'Error: ' + 
                    arg.message + '\n' + arg.stack : arg.stack;
                } else if (arg.sourceURL) {
                    arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line;
                }
            }
            return '[' + name+ '] ' + arg;
        }

        function consoleLog(type, parent, name) {
            var console = $window.console || {},
                logFn = console[type] || console.log || angular.noop;
            if (logFn.apply) {
                var args = [];
                angular.forEach(parent, function(arg) {
                    args.push(formatError(arg, name));
                });
                logFn.apply(console, args);
            }
        }

        function configure(_conf) {
            if (!_conf.consoleThreshold || !(_conf.consoleThreshold >= 1 && _conf.consoleThreshold <= 5)) {
                _conf.consoleThreshold = 4;
            }
            if (!_conf.httpThreshold || !(_conf.httpThreshold >= 1 && _conf.httpThreshold <= 5)) {
                _conf.httpThreshold = 1;
            }
            var keys = Object.keys(config);
            angular.forEach(keys, function (item) {
                if(_conf[item]){
                    config[item] = _conf[item];
                }
                
            });
        }

        function setResource(_resouce) {
            resource = _resouce;
        }

        function formatMessage(_type, level, name) {
                return function () {
                    var timestamp = (new Date()).toISOString();
                    var module = rootname;
                    if (name) {
                        module = module + ':' + name;
                    }
                    var log = {
                        root: rootGuid,
                        timestamp: timestamp,
                        message: [].slice.call(arguments) || '',
                        level: _type,
                        url: $location.absUrl(),
                        name: module
                    };
                    if (arguments[0] instanceof Error && window.printStackTrace) {
                        log.stacktrace = window.printStackTrace({
                            e: arguments[0]
                        });
                    }
                    if (config.httpPath && level <= config.httpThreshold) {
                        resource.save(log);
                    }
                    if (level <= config.consoleThreshold) {
                        switch (level) {
                        case 5:
                            consoleLog('debug',arguments, module);
                            break;
                        case 4:
                            consoleLog('log',arguments, module);
                            break;
                        case 3:
                            consoleLog('info',arguments, module);
                            break;
                        case 2:
                            consoleLog('warn',arguments, module);
                            break;
                        case 1:
                            consoleLog('error',arguments, module);
                            break;
                        }

                    }

                };
            }
            /*jshint bitwise: true*/
        function trmrguid() {
            return 'xxxxxxxxxxxx4xxxyxxxxxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
                var r = Math.random() * 16 | 0,
                    v = c === 'x' ? r : (r & 0x3 | 0x8);
                return v.toString(16);
            });
        }

        return {
            configure: configure,
            $get: ['$resource', '$location', '$window', function($resource, $location,$window) {
                var urlPath = config.httpPath;
                if(config.httpDomain){
                    urlPath = 'http://' + config.httpDomain + urlPath;
                }
                var WS = $resource(urlPath,
                    null, {
                        save: {
                            method: 'POST',
                            headers: {
                                common: {
                                    'x-cobalt-pcid': trmrguid()
                                }
                            }
                        }
                    });
                setResource(WS);
                setInit($window, $location);
                return {
                    debug: formatMessage('debug', 5),
                    log: formatMessage('log', 4),
                    info: formatMessage('info', 3),
                    warn: formatMessage('warn', 2),
                    error: formatMessage('error', 1),
                    getLogger: function(value) {
                        if (arguments.length > 1) {
                            var temp = Array.apply(null, arguments);
                            value = temp.join(':');
                        }
                        return {
                            debug: formatMessage('debug', 5, value),
                            log: formatMessage('log', 4,value),
                            info: formatMessage('info', 3, value),
                            warn: formatMessage('warn', 2, value),
                            error: formatMessage('error', 1, value)
                        };
                    }

                };
            }]
        };
    }

}());
describe('FefLogger with config setting the httpThreshold.', function() {
    var FefLogger, httpBackend, rootScope, message;
    beforeEach(module('fef'));
    beforeEach(module('ngResource'));

    beforeEach(function() {
        var myModule = angular.module('fef');
        myModule.config(function(fefLoggerProvider) {
            fefLoggerProvider.configure({
                httpThreshold: 4,
                consoleThreshold: 1
            });
        });
    });
    var windowMock = {
        navigator: {},
        document: {}
    };
    var myConsole = {
        log: function(value) {
            message = value;
        },
        warn: function(value) {
            message = value;
        },
        info: function(value) {
            message = value;
        },
        error: function(value) {
            message = value;
        },
        debug: function(value) {
            message = value;
        }
    };
    windowMock.console = myConsole;

    beforeEach(module(function($provide) {
        $provide.value('$window', windowMock);
    }));
    afterEach(function() {
        message = '';
    });
    /*jshint camelcase: false */
    beforeEach(inject(function(_fefLogger_, $httpBackend, $window, $rootScope) {
        FefLogger = _fefLogger_;
        spyOn(myConsole, 'error').and.callThrough();
        spyOn(myConsole, 'warn').and.callThrough();
        spyOn(myConsole, 'info').and.callThrough();
        spyOn(myConsole, 'log').and.callThrough();
        spyOn(myConsole, 'debug').and.callThrough();
        httpBackend = $httpBackend;
        rootScope = $rootScope;
    }));
    it('check to see if we can create a FefLogger', function() {
        expect(!!FefLogger).toBe(true);
    });

    it('test log works with http call.', function() {
        var success = true;
        httpBackend.expectPOST('/demo/logs')
            .respond(
                function(method, url, data, headers) {
                    var validData = {
                        message: ['test'],
                        level: 'log',
                        name: 'fef'
                    };
                    data = JSON.parse(data);
                    if (data.message[0] === validData.message[0] &&
                        data.level === validData.level &&
                        data.name === validData.name) {
                        return [200, {
                            token: '12345'
                        }];
                    } else {
                        success = false;
                        return [400, {
                            failure: 'bad'
                        }];
                    }
                });
        FefLogger.log('test');
        expect(myConsole.log).not.toHaveBeenCalled();
        httpBackend.flush();
        expect(success).toBe(true);

    });
    it('test debug is not called call.', function() {
        var success = true;
        httpBackend.expectPOST('/demo/logs')
            .respond(
                function(method, url, data, headers) {
                    var validData = {
                        message: ['test'],
                        level: 'debug',
                        name: 'fef'
                    };
                    data = JSON.parse(data);
                    if (data.message[0] === validData.message[0] &&
                        data.level === validData.level &&
                        data.name === validData.name) {
                        return [200, {
                            token: '12345'
                        }];
                    } else {
                        success = false;
                        return [400, {
                            failure: 'bad'
                        }];
                    }
                });
        FefLogger.debug('test');
        expect(httpBackend.flush).toThrowError('No pending request to flush !');

    });
    it('test mult call is correct format.', function() {
        var success = true;
        httpBackend.expectPOST('/demo/logs')
            .respond(
                function(method, url, data, headers) {
                    var validData = {
                        message: ['test'],
                        level: 'log',
                        name: 'fef:log1'
                    };
                    data = JSON.parse(data);
                    if (data.message[0] === validData.message[0] &&
                        data.level === validData.level &&
                        data.name === validData.name) {
                        return [200, {
                            token: '12345'
                        }];
                    } else {
                        success = false;
                        return [400, {
                            failure: 'bad'
                        }];
                    }
                });
        var log1 = FefLogger.getLogger('log1');
        log1.log('test');
        httpBackend.flush();
        expect(success).toBe(true);

    });
});
<!DOCTYPE html>
<html>

  <head>
    <meta charset="utf-8" />
    <title>Test Template</title>
    
    <!-- Load up Jasmine -->
    <link data-require="jasmine@*" data-semver="2.0.0" rel="stylesheet" href="//cdn.jsdelivr.net/jasmine/2.0.0/jasmine.css" />
  <script data-require="jasmine@*" data-semver="2.0.0" src="//cdn.jsdelivr.net/jasmine/2.0.0/jasmine.js"></script>
  <script data-require="jasmine@*" data-semver="2.0.0" src="//cdn.jsdelivr.net/jasmine/2.0.0/jasmine-html.js"></script>
  <script data-require="jasmine@*" data-semver="2.0.0" src="//cdn.jsdelivr.net/jasmine/2.0.0/boot.js"></script>
    
    <script src="http://code.angularjs.org/1.4.0-beta.6/angular.js"></script>
    <script src="http://code.angularjs.org/1.4.0-beta.6/angular-resource.js"></script>
    <script src="http://code.angularjs.org/1.4.0-beta.6/angular-mocks.js"></script>
    
    <!-- The application code -->
    <script src="app.js"></script>
    
    <!-- The test specs -->
    <script src="app.spec.js"></script>
      </head>

  <body>
    <!-- Unit tests are displayed here -->
    <div id="HTMLReporter" class="jasmine_reporter"></div>
  </body>

</html>