if (typeof util === "undefined") {
    var util = {};
}

if (!util.log) {
    util.log = (function() {
        // public interface
        return {
            debug: function(message) {
                log(message, "debug");
            },

            info: function(message) {
                log(message, "info");
            },

            warn: function(message) {
                log(message, "warn");
            },

            error: function(message) {
                log(message, "error");
            },

            duration: function(startTime, message) {
                var now = new Date();
                if (startTime) {
                    var durationTime = now.getTime() - startTime.getTime();
                    message = message + " (ms): " + durationTime;
                }
                log(message, "debug");
                return now;
            }
        };

        // private methods
        function log(message, level) {
        try {
                if (window.console && !!message) {
                    var now = new Date();
                    getLoggingFunction(level).call(this, now + getCallerString() + ": " + message);
                }
            } catch (err){
               console.log("log.js logging don't work!");
            }
        }

        function getLoggingFunction(level) {
            var loggingFunction;
            if (!!level) {
                switch (level.toLowerCase()) {
                case "debug":
                    loggingFunction = window.console.debug;
                    break;
                case "info":
                    loggingFunction = window.console.info;
                    break;
                case "warn":
                    loggingFunction = window.console.warn;
                    break;
                case "error":
                    loggingFunction = window.console.error;
                    break;
                }
            }
            // return non undefined logging function
            return loggingFunction || window.console.log || function(){};
        }

        function getCallerString() {
            // gets the inner caller object (deep 3)
            var caller = arguments.callee.caller.caller.caller;
            if (!!caller && !!caller.name) {
                return " [" + caller.name + "]";
            }
            return "";
        }
    })();
}
