/**
 * The global namespace.
 */

var sa = {
    extend: Backbone.Model.extend

    , convert: function(str, replacements) {
        var buff = (str||'').split('');
        var i, length = buff.length, t;
        for(i = 0; i < length; i += 1) {
            if((t = replacements[buff[i]])) buff[i] = t;
        }
        return buff.join('');
    }
  
    , encodeHTML: function(string) {
        return string.replace(/&(?!\w+;|#\d+;|#x[\da-f]+;)/gi, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;').replace(/'/g, '&#x27;').replace(/\//g,'&#x2F;');
      }


    , encodeSafeHTML: function (str) {
        return sa.convert(str,  {
          '&': '&amp;',
          '<': '&lt;',
          '>': '&gt;',
          '"': '&quot;'
        });
    }

    , encodeSafeURI: function(str) {
        // TODO make it safe from unicode encoded versions too
        return sa.convert(str, {
            '<': encodeURIComponent('<')
            , '>': encodeURIComponent('>')
            , "'": encodeURIComponent("'")
        });
    }

    , toTitle: function(str) {
        return str.replace(/\w\S*/g, function(txt) {
            return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
        });
    }
};

sa.Msg = (function() {
    function show(type, msg) {
        return $('#msg').html(msg).attr('class', type)[0];
    }

    return {
        clear: function() {
            return $('#msg').html('');
        }
        , error: function(msg) {
            return show.call(this, 'error', msg);
        }
        , info: function(msg) {
            return show.call(this, 'info', msg);
        }
        , warn: function(msg) {
            return show.call(this, 'warn', msg);
        }
    }
})();

sa.Acts = (function() {
    var contexts = null;

    function findActionContext(name) {
        return _.detect(contexts, function(context) {
            return !!_.detect(context.actions, function(value, _name) {
                return name === _name;
            });
        })
    }

    function act(name, arg) {
        sa.Msg.clear();
        console.log('action: ' + name);
        var context = findActionContext(name);
        if(!context) {
            console.error('Action context not found!', name, contexts);
            return sa.Msg.warn('no context found for action: ' + name);
        }

        var action = context.actions[name];
        var fn = context[action.fn];
        if(!fn)
            return sa.Msg.error('Function not found: ' + action.fn);

        fn.call(context, arg); 
    }

    return {
        act: act

        , setContexts: function(_contexts) {
            contexts = _.compact(_contexts);
        }

        , show: function() {
            // TODO show available actions in a help window
            context.actions;
        }
    }
})();

$(document).delegate('.btn[action]', {
    click: function(event) {
        event.preventDefault();
        sa.Acts.act($(event.target).attr('action'),
                    $(event.target).attr('arg'));
    }
});

$(document).delegate('a[path]', {
    click: function(event) {
        if(Backbone.history) {
            event.preventDefault();
            Backbone.history.navigate($(event.target).attr('path'), true);
        }
    }
});

console = typeof(console) !== 'undefined' ? console : {
    log: function(){}
    , error: function(msg) {
        sa.Msg.error(msg);
    }
    , warn: function(msg) {
        sa.Msg.warn(msg);
    }
}

