/*global $, window, alert, console*/
"use strict";

(function () {
    
    $.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);
        }
    };
    
    $.isWebKit = (/WebKit/).test(navigator.userAgent);
    
    $.isIE6 = (/MSIE\s6/).test(navigator.userAgent);
    $.isIE7 = (/MSIE\s7/).test(navigator.userAgent);
    $.isIE8 = (/MSIE\s7/).test(navigator.userAgent);
    
    $.isIE67 = (/MSIE\s[67]/).test(navigator.userAgent);
    $.isIE678 = (/MSIE\s[678]/).test(navigator.userAgent);
    
    
    $.create = function (newElementObject) { 
        
        // custom create HTML
        var neo = newElementObject,
			neoLength = neo.length || 0,
	        tagName = (neo && neo.tagName) ? neo.tagName : "div",
	        newElement = document.createElement(tagName),
	        ne = newElement,
	        p, // properties
	        i = 0,
			clone = null,
			clones = neo.repeat ? true : false,
			df = document.createDocumentFragment(),
			dynProp = null, //dynamic property
			breakLoop = false;

        if (neo.type) {
            ne.setAttribute("type", neo.type);
        }
        
        if (neo.src) {
            ne.setAttribute("src", neo.src);
        }
        
        if (neo) {
            
            if ($.isArray(neo)) {
                
                df = document.createDocumentFragment();
                
                for (i = 0; i < neoLength; i += 1) {
                    try {
                        df.appendChild($.create(neo[i]));
                    } catch (e) {
                        alert(e + "\n\ntagName = " + tagName + "\n\n" + p + ":\n" + neo[p] + "\n\ncreate loop (isArray)");
                        break;
                    }
                }
                
                newElement = df;
            } else {
            
                for (p in neo) {
					
					if ((/(string|function|object|number)/).test(typeof neo[p])) {
					
	                    if ((/^((un)?load|(dbl)?click|change|resize|scroll|select|submit|focus(in|out)?|blur|mouse(enter|leave|over|out|move|down|up)|key(press|down|up))$/).test(p) && typeof neo[p] === "function") {
	                        $(ne).bind(p, neo[p]);
	                    } else if (typeof neo[p] === "function") {
	                        dynProp = neo[p]();
	                        if (dynProp) {
	                            if (typeof ne.style[p] === "string") {
	                                ne.style[p] = dynProp;
	                            } else {
	                                ne[p] = dynProp;
	                            }
	                        }
	                    } else if (!(/(tagName|appendChildren|type|repeat|src)/).test(p)) {
	                        if (typeof ne.style[p] === "string") {
	                            ne.style[p] = neo[p];
	                        } else {
	                            try {
	                                ne[p] = neo[p];
	                            } catch (f) {
	                                alert(f + "\n\ntagName = " + tagName + "\n\n" + p + ":\n" + neo[p] + "\n\nattribute");
	                                breakLoop = true;
	                            }
	                        }
	                    } else if (p === "appendChildren") {
	                        if (typeof neo[p] === "object" && neo[p].length) {
	                            for (i = 0; i < neo[p].length; i += 1) {
	                                try {
	                                    ne.appendChild($.create(neo[p][i]));
	                                } catch (g) {
	                                    alert(g + "\n\ntagName = " + tagName + "\n\n" + p + ":\n" + neo[p] + "\n\ncreate loop");
	                                    breakLoop = true;
	                                }
	                            }
	                        } else if (typeof neo[p] === "object") {
	                            try {
	                                ne.appendChild($.create(neo[p]));
	                            } catch (h) {
	                                alert(h + "\n\ntagName = " + tagName + "\n\n" + p + ":\n" + neo[p] + "\n\ncreate");
	                                breakLoop = true;
	                            }
	                        }
	                    }
	                    
	                    if (breakLoop) {
	                        break;
	                    }
					}
                }
            }
        }

        if (clones) {
            df = document.createDocumentFragment();

            for (i = 0; i < clones; i += 1) {
                clone = newElement.cloneNode(true);
                df.appendChild(clone);
            }

            newElement = df;
        }

        return newElement;
    };
    
    /*$.stripHTML = function (html) {
        return html.replace(/(<[\/]?([hH][1-6]|[a-zA-Z]+)(\s[a-zA-Z]+(\=[^>]+)?)?(>))/g, "");
    };*/

    $.uniqueId = function (id) {
        var count = 0,
			result;
        /*
        DO NOT REPLACE THE "document.getElementById(id + count)" WITH $("#" + id + count)!
            
        Q:  Why? 
        A:  Because $("#" + id + count) will always return an object (it will never be false, undefinded or null)
        this results in an infinity loop. That is not a good thing.
        */
        if (document.getElementById(id + count)) {
            while (document.getElementById(id + count)) {
                count += 1;
            }
        }

        result = id + count;

        return result;
    };
    
    $.objectWalk = function (obj, func, args) {
        var k,
        ar = args ? args : [];

        if (typeof func !== "function") {
            throw new Error("file: custom.js, Error: " + func + " is not a function");
        }

        for (k in obj) {
            if (obj[k] && typeof obj[k] === "object" && (!obj[k].length && obj[k].length !== 0)) {
                $.objectWalk(obj[k], func, ar);
            }
        }
        func.apply(obj, ar);
    };
    
    $.runAll = function () {
        var that = this,
        obj;
        
        $.objectWalk(that, function () {
            var k;
            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)) {
                    // this generates an Error in JSLInt:
                    // "Problem at line 41 character 26: Bad for in variable 'k'."
                    
                    // I have no idea what it should be called to be a 'good one'.
                    // The 'k' variable is apparently ok in '$.objectWalk'...
                    obj = this[arguments[0]];
                    for (k in obj) {
                        if (typeof obj[k] === "function") {
                            obj[k]();
                        }
                    }
                }
            }
        }, [arguments[0]]);
    };
    
    $.runInit = function (obj) {
        $.runAll.apply(obj, ["init"]);
    };
    
}());
