/*global window*/
(function (window) {
    "use strict";
    var $ = window.jQueryFixed ? window.jQueryFixed : window.jQuery;
		
	$.log = function (message) {
        if (window.console && window.console.debug) {
            console.debug(arguments);
        } else if (window.console && window.console.log) {
            console.log(arguments);
        } else {
            alert(message);
        }
    };

    $.fn.normalize = function normalize() {
        var that = this,
            i = 0,
            l = that.length,
            removeEmptyTextNodes = function removeEmptyTextNodes(elem, elem2) {
                
                if (typeof elem !== "object" && elem2) {
                    elem = elem2;
                } else if (typeof elem !== "object") {
                    return;
                }

                var childNodes = elem.childNodes,
                    i = 0,
                    l = childNodes.length,
                    text = elem.innerText ? elem.innerText : elem.textContent;

                if (l) {
                    for (i = (l - 1); i > -1; i -= 1) {
                        if (childNodes[i].nodeType === 3 && !childNodes[i].childNodes.length && !$.trim(text)) {
                            childNodes[i].parentNode.removeChild(childNodes[i]);
                        }
                    }
                }
            };

        for (i = 0; i < l; i += 1) {
            removeEmptyTextNodes(that[i]);

            $(that[i]).find("*").each(removeEmptyTextNodes);
        }

        return that;
    };

	$.fn.bindEvent = function () {
        var ev = arguments[0].event,
			callback = arguments[0].callback,
			l = callback.length,
			callbackMethod,
			i,
			bindMethod = function (e) {
                var arg = [],
					x; 
					
				try {
					for (x = 1; x < arguments.length; x += 1) {
						arg.push(arguments[x]);	
					}
					
					e.data.n[e.data.f].apply(e.data.n, arg);
                } catch (err) {
					$.log(err.message);
                }
            };
		
			
        for (i = 0; i < l; i += 1) {
            callbackMethod = callback[i];
            $(this).bind(ev, callbackMethod, bindMethod);
        }
    };
	
	$.objectWalk = function (obj, func, args) {
        var i,
			ar = args ? args : [];
 
        if (typeof func !== "function") {
            throw new Error("file: custom.js, Error: " + func + " is not a function");
        }
        func.apply(obj, ar);
 
        for (i in obj) {
            if (obj[i] && typeof obj[i] === "object" && (!obj[i].length && obj[i].length !== 0)) {
                $.objectWalk(obj[i], func, ar);
            }
        }
    };
   
    $.runAll = function () {
        var that = this;
       
        $.objectWalk(that, function () {
            if (this[arguments[0]]) {
                if (typeof this[arguments[0]] === "function") {
                    this[arguments[0]]();
                } else if (typeof this[arguments[0]] === "object" && (!this[arguments[0]].length && this[arguments[0]].length !== 0)) {
                    
                    var obj = this[arguments[0]],
                        prop;
                    for (prop in obj) {
                        if (typeof obj[prop] === "function") {
                            obj[prop]();
                        }
                    }
                }
            }
        }, [arguments[0]]);
    };

    /**
     * $.runWhenExists will run a maximum of 50 times before trying to run the callback.
     * If that does not work it does nothing.
     *
     * @param {Function} exists (have to return a falsy or truthy value)
     * @param {Function} callback (will run when "exists" returns a truthy value)
     * @param {Number}
     * @param {Number}
     */
    $.runWhenExists = function runWhenExists(exists, callback, customTime, customWait) {
        
        var iv = 0,
            ivCount = 0,
            time = (customTime && typeof customTime === "number") ? customTime : 100,
            wait = (customWait && typeof customWait === "number") ? customWait : 100,
            allCount = 0,
            maxCount = 50,
            runFunc = function () {
                ivCount += 1;
                allCount += 1;

                if (allCount >= maxCount) {
                    clearInterval(iv);
                    try {
                        callback();
                    } catch (error) {
                        //throw new Error(error);
                    }
                }

                if (exists()) {
                    // wait 100 or [customWait] ms before running the callback, just in case...
                    clearInterval(iv);
                    setTimeout(callback, wait);
                }

                if (ivCount === 5) {
                    clearInterval(iv);

                    time = (time * 2);
                    ivCount = 0;

                    iv = setInterval(runFunc, time);
                }
            };

        iv = setInterval(runFunc, time);

    };

   
    $.runInit = function (obj) {
        $.runAll.apply(obj, ["init"]);
    };

    $.extendView = function extendView(obj) {
        if ($.view) {
            $.extend(true, $.view, obj);
        } else {
	        $.extend({ view: obj });
        }
    };
	
}(window));
