/**
 * @author msalla
 */
var Pb = Pb ||
{};

(function() {
    if (window.jQuery) {
        (function($) {
            /**
             * Portalbuilder Pb.Utils namespace and functions.
             * @author msalla
             * @namespace Pb.Utils
             */
            var TUtils = function() {
            
                /**
                 * Generates a random number inside a given range.
                 * @access private
                 * @static
                 * @param {Object} range
                 */
                var getRandomNumber = function(range) {
                    return Math.floor(Math.random() * range);
                };
                /**
                 * Generates a random alphabetic character.
                 * @access private
                 * @static
                 */
                var getRandomAplhaChar = function() {
                    var chars = "abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ";
                    return chars.substr(getRandomNumber(52), 1);
                };
                /**
                 * Generates a random alphanumeric character.
                 * @access private
                 * @static
                 */
                var getRandomChar = function() {
                    var chars = "0123456789abcdefghijklmnopqurstuvwxyzABCDEFGHIJKLMNOPQURSTUVWXYZ";
                    return chars.substr(getRandomNumber(62), 1);
                };
                /**
                 * Generates a random alphanumeric string of a given size.
                 * @access private
                 * @static
                 * @param {int} size - The text size of the random id to generate
                 * @param {int} alphaStart - Starts with an alphanumeric char.
                 * @return {string} - The random generated id.
                 */
                var randomId = function(size, alphaStart) {
                    var str = alphaStart ? getRandomAplhaChar() : "";
                    for (var i = alphaStart ? 1 : 0; i < size; i++) {
                        str += getRandomChar();
                    }
                    return str;
                };
                
                /**
                 * Basic system utilities. In the future we should migrate progressively the
                 * current seUtils here or as an extension plugin.
                 * @namespace Pb.Utils
                 */
                function Utils() {
                }
                Utils.prototype = {
                    /**
                     * Gets the most accessible top window. Used in the backoffice to set
                     * common global object references and global event bindings. If the
                     * most top window is not accessible because of SDP then the current
                     * window is returned instead.
                     */
                    safeGetWindowTop: function() {
                        try {
                            //We should allways try to use the top window acting as the coordinator.
                            if ((window.top != window) && window.top.document.readyState) {
                                return window.top;
                            }
                            else {
                                return window;
                            }
                        } 
                        catch (e) {
                            // Probably an access denied error because of XDS
                            return window;
                        }
                    },
                    /**
                     * Curry delegate function. If Ms ajax framework is present we use it.
                     * @param {Object} aInstance - Object context method.
                     * @param {Function} aFunction - Function to be called.
                     * @return - The function delegate.
                     * @type {Function}
                     */
                    createDelegate: Function.createDelegate ||
                    function(aInstance, aFunction) {
                        return function() {
                            return aFunction.apply(aInstance, arguments);
                        };
                    },
                    /**
                     * From O'Reilly Javascript and DHTML Cookbook:
                     * To determine the mouse event location in the coordinate plane of the entire
                     * document, the getPageEventCoords( ) function shown in the following example
                     * has two main branches. The first gets the simpler pageX and pageY properties
                     *  of the Netscape event object. For IE, many more calculations need to be
                     * carried out to derive the coordinates to accurately position an element at
                     * the specified location. The clientX and clientY properties need additional
                     * factors for any scrolling of the body content and some small padding that
                     * IE automatically adds to the body (normally two pixels along both axes).
                     * In the case of IE 6 running in CSS-compatibility mode, the html element's
                     * small padding must also be factored out of the equation.
                     * @param {Object} evt
                     */
                    getPageEventCoords: function(evt) {
                        var coords = {
                            left: 0,
                            top: 0
                        };
                        if (evt.pageX) {
                            coords.left = evt.pageX;
                            coords.top = evt.pageY;
                        }
                        else 
                            if (evt.clientX) {
                                coords.left = evt.clientX + document.body.scrollLeft - document.body.clientLeft;
                                coords.top = evt.clientY + document.body.scrollTop - document.body.clientTop;
                                // include html element space, if applicable
                                if (document.body.parentElement && document.body.parentElement.clientLeft) {
                                    var bodParent = document.body.parentElement;
                                    coords.left += bodParent.scrollLeft - bodParent.clientLeft;
                                    coords.top += bodParent.scrollTop - bodParent.clientTop;
                                }
                            }
                        return coords;
                    },
                    /**
                     * Clears the current text selection.
                     */
                    clearTextSelection: function() {
                        var sel;
                        if (document.selection && document.selection.empty) {
                            document.selection.empty();
                        }
                        else 
                            if (window.getSelection) {
                                sel = window.getSelection();
                                if (sel && sel.removeAllRanges) {
                                    sel.removeAllRanges();
                                }
                                if (sel && sel.collapse) {
                                    sel.collapse();
                                }
                            }
                    },
                    /**
                     * Gets the global object reference manager.
                     */
                    getGlobal: function() {
                        return this.safeGetWindowTop().seGlobal;
                    },
                    /**
                     * Gets the global object reference refresh manager.
                     */
                    getGlobalRefreshManager: function() {
                        return this.safeGetWindowTop().GlobalRefreshManager;
                    },
                    /**
                     * Generates a random NOT Globally But Locally Unique guid. Returns the guid as a string.
                     */
                    generateGuid: function() {
                        var result, i, j;
                        result = '';
                        for (j = 0; j < 32; j++) {
                            if (j == 8 || j == 12 || j == 16 || j == 20) {
                                result = result + '-';
                            }
                            i = Math.floor(Math.random() * 16).toString(16).toUpperCase();
                            result = result + i;
                        }
                        return result;
                    },
                    /**
                     * Generates a randomClientId
                     * @param {Object} size
                     */
                    generateRandomClientId: function(size) {
                        return randomId(size, true);
                    },
                    /**
                     * Creates a hidden temporary iframe with a given source to provide XSS functionality,
                     * waits for it's load event and then it's destroyed.
                     * @param {uri} aIFrameSrc
                     * @param {function} aCallback : fn(aCallbackData, 'success', aNewIFrame)
                     * @param {object} aCallBackContext
                     * @param {object} aCallbackData
                     */
                    createXssFrame: function(/*string */aIFrameSrc, aCallback, aCallBackContext, aCallbackData) {
                        var lCallBackContext = aCallBackContext ||
                        {};
                        var lCallBackData = aCallbackData || null;
                        var lNewIFrame = document.createElement('iframe');
                        var lNewIFrameId = 'iTempFrame__' + Pb.Utils.generateGuid();
                        lNewIFrame.setAttribute('id', lNewIFrameId);
                        lNewIFrame.style.display = 'none';
                        lNewIFrame.setAttribute('src', aIFrameSrc);
                        document.body.appendChild(lNewIFrame);
                        function checkIframeLoading() {
                            try {
                                // Check if loading is complete
                                if (lNewIFrame.document.readyState == 'complete') {
                                    // The loading is complete, call the function we want executed once the iframe is loaded
                                    try {
                                        aCallback.apply(lCallBackContext, [aCallbackData, 'success', lNewIFrame]);
                                    } 
                                    catch (ex) {
                                        //alert(ex.message);
                                    }
                                    document.body.removeChild(lNewIFrame);
                                    return;
                                }
                                // If we are here, it is not loaded. Set things up so we check   the status again in 100 milliseconds
                                window.setTimeout(checkIframeLoading, 100);
                            } 
                            catch (ex) {
                            }
                        }
                        checkIframeLoading();
                    },
                    /**
                     * Sets an iframe new url with steroids.
                     * @param {Object} aIframe : to change the url to.
                     * @param {Object} url : New iframe url.
                     * @param {Object} onLoad : function to be executed on iframe load event.
                     * @param {Object} options : Steroid options.
                     * 	{
                     * 		timeout : 0, // frame timeout in milliseconds
                     * 		onTimeout : null, //timeout callback function. function(iframe,timeoutElapdsedMilliSeconds)
                     * 		onReady: null //on iframe ready callback function. function(iframe,readyElapdsedMilliSeconds)
                     * 	}
                     */
                    setIframeUrl: function(aIframe, url, onLoad, options) {
                        var iframe = $(aIframe);
                        var timer = iframe.data("timer");
                        iframe.unbind("load");
                        if (timer) {
                            clearTimeout(timer);
                            iframe.data("timer", null);
                        }
                        
                        var defaults = {
                            timeout: 0,
                            onTimeout: null,
                            onReady: null
                        };
                        var opts = $.extend(defaults, options);
                        
                        opts.frameactive = true;
                        
                        var startTime = (new Date()).getTime();
                        
                        if (opts.timeout) {
                            iframe.data("timer", setTimeout(function() {
                                opts.frameactive = false;
                                iframe.load(null);
                                if (opts.onTimeout) {
                                    opts.onTimeout(iframe.get(0), opts.timeout);
                                }
                            }, opts.timeout));
                            timer = iframe.data("timer");
                        }
                        
                        if (opts.onReady) {
                            iframe.unbind("ready");
                            iframe.ready(function() {
                                if (opts.frameactive) {
                                    var duration = (new Date()).getTime() - startTime;
                                    opts.onReady(this, duration);
                                }
                            });
                        }
                        
                        var onloadHandler = function() {
                            var duration = (new Date()).getTime() - startTime;
                            if (iframe.data("timer")) {
                                clearTimeout(timer);
                                iframe.data("timer", null);
                            }
                            if (onLoad && opts.frameactive) {
                                onLoad(this, duration);
                            }
                            opts.frameactive = false;
                        };
                        iframe.attr("src", url);
                        iframe.get()[0].onload = onloadHandler;
                        iframe.data("onloadHandler", onloadHandler);
                        opts.completeReadyStateChanges = 0;
                        var IeOnlyOnreadystatechange = function() { // IE ftw
                            if (++(opts.completeReadyStateChanges) == 3) {
                                onloadHandler();
                            }
                        };
                        iframe.get()[0].onreadystatechange = IeOnlyOnreadystatechange;
                        iframe.data("onreadystatechange", IeOnlyOnreadystatechange);
                    },
                    /**
                     * Clear the iFrame operation timer and load function.
                     * @param {Object} aIframe
                     */
                    clearIframeOperationTimer: function(aIframe) {
                        var iframe = $(aIframe);
                        var timer = iframe.data("timer");
                        if (timer) {
                            clearTimeout(timer);
                            iframe.data("timer", null);
                        }
                        iframe.unbind("load", iframe.data("onloadHandler"));
                        iframe.get()[0].onreadystatechange = null;
                    },
					/**
                     * Includes JavaScript file in the head of the page dinamically.
                     * Non compatible safari versions (maybe < v2.0)
                     * @param {String} scriptUrl.
                     */
                    includeJs: function(scriptUrl) {
                        // Handle multiple include attempts 
                        if ($("script[src='" + scriptUrl + "']").size() === 0) {
                            $('head').createAppend('script', {
                                type: 'text/javascript',
                                src: scriptUrl
                            });
                        }
                    },
                    /**
                     * Includes JavaScript file in the head of the iframe document dinamically.
                     * Non compatible safari versions (maybe < v2.0)
                     * @param {String} scriptUrl.
                     */
                    includeIframeJs: function(aIframe,scriptUrl) {
						var lIframeElContentWindow = aIframe.contentWindow || (aIframe.contentDocument ? aIframe.contentDocument.defaultView : null);
						// TODO: Avoid the need for jQuery in the iFrame window.
						if (lIframeElContentWindow && lIframeElContentWindow.document) {
							var jDoc = $(lIframeElContentWindow.document);
							// Handle multiple include attempts 
							if (jDoc.find("script[src='" + scriptUrl + "']").size() === 0) {
								jDoc.find('head').createAppend('script', {
									type: 'text/javascript',
									src: scriptUrl
								});
							}
						}
                    },
                    /**
                     * Loads and executes a local JavaScript file dinamically synchronously.
                     * @param {String} scriptUrl
                     */
                    loadScript: function(scriptUrl) {
                        // Change requests to be sent synchronous 
                        $.ajaxSetup({
                            async: false
                        });
                        try {
                            // Loads and executes a local JavaScript file 
                            $.getScript(scriptUrl);
                        }
                        finally {
                            // Restore requests to be sent asynchronous 
                            $.ajaxSetup({
                                async: true
                            });
                        }
                    }
                    
                };
                return {
                    Utils: new Utils()
                };
            }();
            $.extend(Pb, TUtils);
            
            $.pbUtils = Pb.Utils;
            
            //var extensions = {
            //};
        
            //$.each( extensions, function( i )
            //{
            //	$.fn[i] = this;
            //});
        })(window.jQuery);
    }
})();
