var vsb = {};

var VZT = {};

VZT.AppCore = null;
/**
* This is the base class for the entire library.  All classes should implement this class.
* @class Core
* @namespace Lib
* @static
*/
VZT.Base = {


    /**
    * Copies properties to current class.  Used in place of setOptions.
    * @method setProperties
    * @param {Object} options The properties to copy 
    * @return {Object} The current instance
    */
    setProperties: function (o) {
        this.appCore = VZT.AppCore;
        this._setGlobalProperties();
        if ($chk(o)) {
            for (var option in o) {
                if (o.hasOwnProperty(option)) {
                    this[option] = o[option];
                }
            }
        }
        this.initCustomEvents();
        return this;
    },

    /**
    * Copies properties defined in LibOptions to current class.
    * @method _setGlobalProperties
    * @private
    * @return {Object} The current instance 
    */
    _setGlobalProperties: function () {
        //check to see if _name is defined, as it needs this to do a lookup in LibOptions
        if (typeof this._name !== 'undefined' && typeof LibOptions !== 'undefined') {
            if (typeof LibOptions[this._name] !== 'undefined') {
                for (var option in LibOptions[this._name]) {
                    if (LibOptions[this._name].hasOwnProperty(option)) {
                        this[option] = LibOptions[this._name][option];
                    }
                }
            }
        }
        return this;
    },

    /**
    * Calls invokeMyEvent(), "MyEvent" being the str passed.  Calls method with args.
    * @method setProperties
    * @param {String} str The event to invoke
    * @param {Array} args The arguments to pass to the event
    */
    invokeEvent: function (str, args) {
        var method = 'invoke' + str.capitalize();
        if ($chk(this[method])) {
            this[method](args);
        }
    },

    /**
    * Gets custom events ready.  They are pulled from the CustomEvents property, if you do not 
    * pass an events param. Two methods are created: invokeMyEvent() and doMyEvent(), "MyEvent"
    * being the event name, converted from camelCase to TitleCase(i.e. 'beforeShow' becomes 
    * 'invokeBeforeShow','doBeforeShow'). Thus, if you want to edit an event after it's already 
    * been added, you edit doMyEvent(). By default, this method contains the MooTools fireEvent()
    * method. invokeMyEvent() simply delegates to doMyEvent().
    * @method initCustomEvents
    * @param {Array} events (Optional) The custom events you want to add
    */
    initCustomEvents: function (events) {
        var e = [];

        if ($chk(events)) {
            e = events;
        } else if ($chk(this.CustomEvents) && !$chk(this._customEventsInitialized)) {
            e = this.CustomEvents.flatten();
            this._customEventsInitialized = true;
        }
        e.each(function (event) {
            this.initCustomEvent(event);
        } .bind(this));
        return this;
    },
    /**
    * Initializes the custom events
    * @method initCustomEvent
    * @param {String?} e - The names of the event
    */
    initCustomEvent: function (e) {
        var cap = e.capitalize();
        this['invoke' + cap] = function (args) {
            if ($chk(this['do' + cap])) {
                this['do' + cap](args);
            }
        } .bind(this);
        this['do' + cap] = function (args) {
            args = ($chk(args)) ? args : null;
            this.fireEvent(e, args);
        } .bind(this);
    },

    /**
    * Handles checking to see if an event needs to be fired
    * for a given event bubble and module
    * @param event
    * @param strength
    * @param selectors
    */
    bubble: function (event, strength, selectors) {
        try {
            if (event == undefined || event == null)
                return;
            var object = $(event.target);

            for (var i = 0; i < strength; i++) {
                for (selector in selectors) {
                    if (this._matchesselector(object, selector)) {
                        selectors[selector](event, object);
                    }
                }

                if (object == null || object.parentNode == null)
                    break;
                object = object.getParent();


            }
        } catch (e) {
            
        }

    },

    /**
    * matchs elements
    * @param el
    * @param selector
    */
    _matchesselector: function (el, selector) {
        try {
            var classstring = el.get('class');

            var re = new RegExp("\\b[a-z]*" + selector + "[a-z]*\\b");
            return classstring.match(re);
        } catch (e) {
            return false;
        }
    }
};
