(function() {

    /**
     * Merge the contents of two or more objects together into the first object
     * (based on jQuery extend function)
     * @param {Boolean} [recursive] - recursive flag
     * @param {Object} target - target object
     * @param {Object*} [objectN] - object to merge in
     * @return {Object} target object
     */
    Object.extend = function() {
        var n = 1,
            recursive = false,
            target = arguments[0],
            obj,
            name, src, val;

        // check for recursive flag in first argument
        if (typeof target === 'boolean') {
            recursive = target;
            target = arguments[1];
            n = 2;
        }

        if ((typeof target !== 'object') && (typeof target !== 'function')) {
            target = {};
        }

        for ( ; n < arguments.length; n++) {
            if ((obj = arguments[n]) != null) {
                for (name in obj) {
                    src = target[name];
                    val = obj[name];
                    // convert Number and String object to primitives
                    if (typeof val === 'object') {
                        if (val instanceof Number) {
                            val = Number(val);
                        } else if (val instanceof String) {
                            val = String(val);
                        }
                    }
                    // Try to recursive merge if copy is object and nor array or function
                    if ((recursive) && (typeof val === 'object') && (val) && (!(val instanceof Function)) && (!(val instanceof Array))) {
                        target[name] = Object.extend(recursive, src, val);
                    } else if (val !== undefined) {
                        target[name] = val;
                    }
                }
            }
        }
        return target;
    };


    /**
     * Merging content two or more objects recursive to new object
     * @param {Object*} two or more objects
     * @return {Object} the result
     */
    Object.merge = function() {
        var args = [true, {}];
        for (var i = 0; i < arguments.length; i++) {
            args.push(arguments[i]);
        }
        return Object.extend.apply(this, args);
    };


    function __p() {}
    /**
     * Create prototype chain for object
     * @param {Object} child - child object
     * @param {Object} parent - parent object
     * @return {Object} child object
     */
    Object.inherit = function(child, parent) {
        __p.prototype = parent.prototype || {};
        child.prototype = new __p();
        child.prototype.constructor = child;
        child.SUPER = parent.prototype;
        return child;
    };



    // Aliases to Function() object

    /**
     * Add prototype chain to object
     * @param {Object} parent - parent object
     * @return {Object}
     */
    Function.prototype.inherit = function(parent) {
        return Object.inherit(this, parent);
    };

    /**
     * Extend object prototype
     * @param {object} proto
     * @return {Function}
     */
    Function.prototype.proto = function(proto) {
        Object.extend(this.prototype, proto);
        return this;
    };
})();
