"use strict";

define(

  [
    '../../lib/registry',
    '../../lib/utils'
  ],

  function(registry, utils) {

    var logFilter;

    //******************************************************************************************
    // Search object model
    //******************************************************************************************

    function traverse(util, searchTerm, options) {
      var options = options || {};
      var obj = options.obj || window;
      var path = options.path || ((obj==window) ? "window" : "");
      var props = Object.keys(obj);
      props.forEach(function(prop) {
        if ((tests[util] || util)(searchTerm, obj, prop)){
          console.log([path, ".", prop].join(""), "->",["(", typeof obj[prop], ")"].join(""), obj[prop]);
        }
        if(Object.prototype.toString.call(obj[prop])=="[object Object]" && (obj[prop] != obj) && path.split(".").indexOf(prop) == -1) {
          traverse(util, searchTerm, {obj: obj[prop], path: [path,prop].join(".")});
        }
      });
    }

    function search(util, expected, searchTerm, options) {
      if (!expected || typeof searchTerm == expected) {
        traverse(util, searchTerm, options);
      } else {
        console.error([searchTerm, 'must be', expected].join(' '))
      }
    }

    var tests = {
      'name': function(searchTerm, obj, prop) {return searchTerm == prop},
      'nameContains': function(searchTerm, obj, prop) {return prop.indexOf(searchTerm)>-1},
      'type': function(searchTerm, obj, prop) {return obj[prop] instanceof searchTerm},
      'value': function(searchTerm, obj, prop) {return obj[prop] === searchTerm},
      'valueCoerced': function(searchTerm, obj, prop) {return obj[prop] == searchTerm}
    }

    function byName(searchTerm, options) {search('name', 'string', searchTerm, options);};
    function byNameContains(searchTerm, options) {search('nameContains', 'string', searchTerm, options);};
    function byType(searchTerm, options) {search('type', 'function', searchTerm, options);};
    function byValue(searchTerm, options) {search('value', null, searchTerm, options);};
    function byValueCoerced(searchTerm, options) {search('valueCoerced', null, searchTerm, options);};
    function custom(fn, options) {traverse(fn, null, options);};

    //******************************************************************************************
    // Event logging
    //******************************************************************************************
    var logLevel = [];
    logFilter = {actions: logLevel, eventNames: logLevel}; //no filter by default

    function filterEventLogsByAction(/*actions*/) {
      var actions = [].slice.call(arguments, 0);

      logFilter.eventNames.length || (logFilter.eventNames = 'all');
      logFilter.actions = actions.length ? actions : 'all';
    }

    function filterEventLogsByName(/*eventNames*/) {
      var eventNames = [].slice.call(arguments, 0);

      logFilter.actions.length || (logFilter.actions = 'all');
      logFilter.eventNames = eventNames.length ? eventNames : 'all';
    }

    function hideAllEventLogs() {
      logFilter.actions = [];
      logFilter.eventNames = [];
    }

    function showAllEventLogs() {
      logFilter.actions = 'all';
      logFilter.eventNames = 'all';
    }

    return {

      enable: function(enable) {
        this.enabled = !!enable;

        if (enable && window.console) {
          console.info('Booting in DEBUG mode');
          console.info('You can configure event logging with DEBUG.events.logAll()/logNone()/logByName()/logByAction()');
        }

        window.DEBUG = this;
      },

      find: {
        byName: byName,
        byNameContains: byNameContains,
        byType: byType,
        byValue: byValue,
        byValueCoerced: byValueCoerced,
        custom: custom
      },

      events: {
        logFilter: logFilter,

        // Accepts any number of action args
        // e.g. DEBUG.events.logByAction("on", "off")
        logByAction: filterEventLogsByAction,

        // Accepts any number of event name args (inc. regex or wildcards)
        // e.g. DEBUG.events.logByName(/ui.*/, "*Thread*");
        logByName: filterEventLogsByName,

        logAll: showAllEventLogs,
        logNone: hideAllEventLogs
      }
    };
  }
);


@@ -2517,87 +2517,63 @@
 var 
-logLevel = %5B%5D;%0A    logFilter = %7Bactions: logLevel, eventNames: logLevel
+defaultLogFilter = %7BeventNames: %5B%5D, actions: %5B%5D
 %7D; //no 
 filt
@@ -2568,22 +2568,23 @@
 %7D; //no 
-filter
+logging
  by defa
@@ -2586,16 +2586,53 @@
  default
+%0A    logFilter = retrieveLogFilter();
 %0A%0A    fu
@@ -2848,32 +2848,55 @@
 ctions : 'all';%0A
+      saveLogFilter();%0A
     %7D%0A%0A    funct
@@ -3116,32 +3116,55 @@
 tNames : 'all';%0A
+      saveLogFilter();%0A
     %7D%0A%0A    funct
@@ -3247,24 +3247,47 @@
 Names = %5B%5D;%0A
+      saveLogFilter();%0A
     %7D%0A%0A    f
@@ -3344,24 +3344,24 @@
 ns = 'all';%0A
-
       logFil
@@ -3380,24 +3380,290 @@
 es = 'all';%0A
+      saveLogFilter();%0A    %7D%0A%0A    function saveLogFilter() %7B%0A      window.localStorage && localStorage.setItem('logFilter', logFilter);%0A    %7D%0A%0A    function retrieveLogFilter() %7B%0A      return window.localStorage ? localStorage.getItem('logFilter') : defaultLogLevel;%0A
     %7D%0A%0A    r

use local storage for logging preferences