/**
 * Patterns logging - minimal logging framework
 *
 * Copyright 2012 Simplon B.V.
 * Copyright 2012 Florian Friesdorf
 */

define([
        "../compat"  // Needed for function.bind
], function() {
    var root,    // root logger instance
        writer;  // writer instance, used to output log entries

    var Level = {
        DEBUG: 10,
        INFO: 20,
        WARN: 30,
        ERROR: 40,
        FATAL: 50
    };

    function IEConsoleWriter() {
    }

    IEConsoleWriter.prototype = {
            output:  function(level, messages) {
            // console.log will magically appear in IE8 when the user opens the
            // F12 Developer Tools, so we have to test for it every time.
            if (console===undefined || console.log===undefined)
                    return;
            for (i=0; i<messages.length; i++)
                if (typeof messages[i]!=="string")
                    messages[i]=messages[i].toString();

            var message = messages.join(" ");

            if (level<=Level.DEBUG) {
                // console.debug exists but is deprecated
                message="[DEBUG]"+message;
                console.log(messages);
            } else if (level<=Level.INFO)
                console.info(message);
            else if (level<=Level.WARN)
                console.warn(message);
            else
                console.error(message);
        }
    };


    function ConsoleWriter() {
    }

    ConsoleWriter.prototype = {
        output: function(level, messages) {
            if (level<=Level.DEBUG) {
                // console.debug exists but is deprecated
                messages.unshift("[DEBUG]");
                console.log.apply(console, messages);
            } else if (level<=Level.INFO)
                console.info.apply(console, messages);
            else if (level<=Level.WARN)
                console.warn.apply(console, messages);
            else
                console.error.apply(console, messages);
        }
    };


    function Logger(name, parent) {
        this._loggers={};
        this.name=name || "";
        this._parent=parent || null;
        if (name==="root") {
            this._enabled=true;
            this._level=Level.INFO;
        }
    }

    Logger.prototype = {
        getLogger: function(name) {
            if (!(name in this._loggers))
                this._loggers[name] = new Logger(name, this);
            return this._loggers[name];
        },

        _getFlag: function(flag) {
            var context=this;
            flag="_"+flag;
            while (context!==null) {
                if (context[flag]!==undefined)
                    return context[flag];
                context=context._parent;
            }
            return null;
        },

        setEnabled: function(state) {
            this._enabled=!!state;
        },

        isEnabled: function() {
            this._getFlag("enabled");
        },

        setLevel: function(level) {
            if (typeof level==="number")
                this._level=level;
            else if (typeof level==="string") {
                level=level.toUpperCase();
                if (level in Level)
                    this._level=Level[level];
            }
        },

        getLevel: function() {
            return this._getFlag("level");
        },

        getFullname: function() {
            var names = [],
                logger = this;
            while (logger.name !== "root") {
                names.unshift(logger.name);
                logger = logger._parent;
            }
            return names.join(".");
        },

        log: function(level, messages) {
            if (!messages.length || !this._getFlag("enabled") || level<this._getFlag("level"))
                return;
            messages=[this.getFullname() + ":"].concat(messages);
            writer.output(level, messages);
        },

        debug: function() {
            this.log(Level.DEBUG, arguments);
        },

        info: function() {
            this.log(Level.INFO, arguments);
        },

        warn: function() {
            this.log(Level.WARN, arguments);
        },

        error: function() {
            this.log(Level.ERROR, arguments);
        },

        fatal: function() {
            this.log(Level.FATAL, arguments);
        }
    };

    function getWriter() {
        return writer;
    }

    function setWriter(w) {
        writer=w;
    }

    if (window.console && window.console.log && window.console.log.apply!==undefined)
        setWriter(new ConsoleWriter());
    else
        setWriter(new IEConsoleWriter());

    root=new Logger("root");

    var logconfig = /pat-loglevel(|-[^=]+)=([^&]+)/g,
        match;

    while ((match=logconfig.exec(window.location.search))!==null) {
        var logger = (match[1]==="") ? root : root.getLogger(match[1].slice(1));
        logger.setLevel(match[2].toUpperCase());
    }

    return {
        Level: Level,
        getLogger: root.getLogger.bind(root),
        setEnabled: root.setEnabled.bind(root),
        isEnabled: root.isEnabled.bind(root),
        setLevel: root.setLevel.bind(root),
        getLevel: root.getLevel.bind(root),
        debug: root.debug.bind(root),
        info: root.info.bind(root),
        warn: root.warn.bind(root),
        error: root.error.bind(root),
        fatal: root.fatal.bind(root),
        getWriter: getWriter,
        setWriter: setWriter
    };
});

@@ -4644,16 +4644,55 @@
 %22root%22);
+%0A    root = root.getLogger(%22patterns%22);
 %0A%0A    va

introduce toplevel patterns logger