//***
//* Check out the Javascript Documentation Wiki for details
//***

//XMLHttpRequest(JK)
if( window.XMLHttpRequest || window.ActiveXObject ){
  	if( window.ActiveXObject ){
		var lib = /MSIE 5/.test(navigator.userAgent) ? "Microsoft" : "Msxml2";
  		window.XMLHttpRequest = function(){	return new ActiveXObject(lib + ".XMLHTTP"); };
  	};
}

// designed to be used as a singleton object, so you probably shouldn't inherit from this guy
CB.AJAX = function () {
    return {
        currentVisiblePopup: null,
        isPopupLocked: false,

        // Cross browser compatible creation of XmlHttpRequest object
        createRequest: function () {
            var request;

            // IE
            try {
                request = new ActiveXObject("Msxml2.XMLHTTP");
            }
            catch (e) {
                try {
                    request = new ActiveXObject("Microsoft.XMLHTTP");
                }
                catch (oc) {
                    request = null;
                }
            }

            // Mozilla
            if (!request && typeof XMLHttpRequest != "undefined") {
                request = new XMLHttpRequest();
            }

            return request;
        },

        // Fires a callback, sending data to page, with the response handled by handler
        submitCallback: function (data, page, handler, lockPopups) {
            var request = this.createRequest();
            if (request) {
                var sAjaxPrefix = '';
                if (ScriptVariables.Contains('sAjaxRelativePrefix')) {
                    sAjaxPrefix = ScriptVariables.Get('sAjaxRelativePrefix');
                } else {
                    sAjaxPrefix = ajaxRelativePrefix;
                }
                if (typeof sAjaxPrefix != 'undefined') {
                    // prefix page with relative path prefix var that was inserted by MatrixPage
                    page = sAjaxPrefix + page;

                    // prepare request
                    request.open('POST', page, true);
                    request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

                    // when the request is answered, relayResponse() will be called
                    request.onreadystatechange = function () { CB.AJAX.relayResponse(request, handler); };

                    CB.AJAX.isPopupLocked = lockPopups;
                    // fire off the request
                    request.send(data);
                    var timer = setTimeout(function () { CB.AJAX.abortRequest(request) }, 10000)

                } else {
                    // relative path var not found, cannot correctly set path to AJAX page
                    handler(false, 'Relative prefix not found (be sure to use Page.HasAjax).');
                }
            } else {
                // request object wasn't instantiated
                handler(false, 'Unable to create request object.');
            }
        },

        // abort an AJAX request on timeout
        abortRequest: function (request) {
            request.abort();
        },

        // Passes response data from a callback to the handler function
        relayResponse: function (request, handler) {
            var responseText;
            var index;
            if (request.readyState == 4) {
                try {
                    if (request.status == 200) {
                        responseText = request.responseText;

                        // ugly hack for international pages adding extra HTML
                        index = responseText.indexOf("<!DOCTYPE");
                        if (index != -1) {
                            responseText = responseText.substring(0, index);
                        }

                        // success, give response text to handler function
                        CB.AJAX.isPopupLocked = false;
                        handler(true, responseText);
                    }
                    else {
                        // page returned error code (such as 404)
                        CB.AJAX.isPopupLocked = false;
                        handler(false, 'Ajax page returned error code ' + request.status + '.');
                    }
                }
                catch (e) {
                    // i hate this, but for now we need to eat the error.  we don't have a sure way of tracking errors
                }
            }
        },
        hidePopups: function () {
            if (CB.AJAX.currentVisiblePopup && !CB.AJAX.isPopupLocked) {
                CB.AJAX.currentVisiblePopup.hide();
            }
            if (window.hideCurrentPopup) {   // this will close windows in the other popup management system
                hideCurrentPopup();
            }
        }
    };
} ();

// the base object of all AJAX widgets.  These will most likely be comprised of DIVs
CB.AJAX.Popup = function ()
{
    function onDocumentClick (evt,target){
        var shadowBox;
        if(CB.AJAX.currentVisiblePopup.documentClickCloses){
			if (!CB.AJAX.currentVisiblePopup.isModal){
				if(target){//if i don't know the target then I can't determine anything
					shadowBox = CB.e('shadowAJAX');
					if(!shadowBox || !shadowBox.lastAnchor || shadowBox.lastAnchor.id != target.id){
						CB.AJAX.hidePopups();
					}
				}
			}
		}
    }
	// find X coordinate of an element:  anchor - the element we are trying to position relative to, element - the element we are positioning
	function findX(anchor, element, halign)	{
	    // we need to be really intelligent about what we spit back out.
		var curleft = 0;
		var leftcenter = anchor.offsetWidth / 3;
		var rightcenter = anchor.offsetWidth - leftcenter;
		if(anchor.offsetParent){
			while(anchor.offsetParent){
				curleft += anchor.offsetLeft;
				anchor = anchor.offsetParent;
			}
		}
		else if(anchor.x){
			curleft += anchor.x;
		}
		
		if(halign && halign === 'flush'){
		    if (curleft > CB.Window.getWidth() / 2) {
		        // we are on the right side of the window		    
		        return (curleft + (leftcenter * 3)) - element.scrollWidth;
		    } else {
		    	// we are on the left side of the window
		    	return curleft;
		    }
		}
		else {
		    if (curleft > CB.Window.getWidth() / 2) {
		        // we are on the right side of the window
		        return (curleft + rightcenter) - (element.scrollWidth);
		    }
		    else {
		        // we are on the left side of the window
		        return curleft + leftcenter;
		    }
	    }
	}

	// find Y coordinate of an element
	function findY(anchor, element)	{
		var curtop = 0;
		if(anchor.offsetParent){
			while(anchor.offsetParent){
				curtop += anchor.offsetTop;
				anchor = anchor.offsetParent;
			}
		}
		else if(anchor.y){
			curtop += anchor.y;
		}
		
		// using a hard number feels like a hack, but it should serve us well
		// I used to use anchor.offsetHeight, but it counts padding and so is inconsistent
		if (!CB.Window.ie) {
		    if (curtop + 20 + element.offsetHeight > CB.Window.getScrollHeight()) {
		        return CB.Window.getScrollHeight() - element.offsetHeight;
		    }
		    else {
		        return curtop + 20;
		    }
		}
		else {
		    if (curtop + 15 + element.offsetHeight > CB.Window.getScrollHeight()) {
		        return CB.Window.getScrollHeight() - element.offsetHeight;
		    }
		    else {				
		        return curtop + 15;
		    }
		}
	}
	
    return {
        containerElm: null,
        parentContainer: null,
        isModal: false,
		documentClickCloses: true,
        halign: null,
    
        initialize: function(container, options){
            // do some initialization here
            this.containerElm = container;
            if (container) {
                this.parentContainer = container.parentNode;
                this.containerElm.style.left = '-3000px';
                this.containerElm.style.top = '0px';
            }
            if(options){
                this.isModal = options.isModal;
				this.documentClickCloses = options.documentClickCloses;
                this.halign = options.halign;
            }
        },
    
        // options is an optional variable where you can stuff any desired parameters for onShow
        show: function(anchor, options, anchorOffsetX, anchorOffsetY){
            // we have to get our shadow
            var shadowBox = CB.e('shadowAJAX');
			var iframeWrapper = CB.e('popupIframe');
            var diff,i;
            
			
			if (!iframeWrapper) {
				//alert('not hit');
				iframeWrapper = document.createElement("iframe");
				iframeWrapper.id = 'popupIframe';
				CB.EventUtils.addEventListener(iframeWrapper, 'click', function(evt,target){evt.cancelBubble = true;});
				iframeWrapper.style.position = 'absolute';
				iframeWrapper.style.background = 0;
				iframeWrapper.style.filter = 'chroma(color=#FFFFFF)';
				iframeWrapper.style.allowTransparency = 'true';
				iframeWrapper.style.frameborder = 'No';
				
				document.body.appendChild(iframeWrapper);
				
	        }
			if (!shadowBox) {
                shadowBox = document.createElement("div");
                shadowBox.className = 'cb_style shadowing';
                shadowBox.style.textAlign = 'left';
                shadowBox.id = 'shadowAJAX';
                CB.EventUtils.addEventListener(shadowBox,'click',function(evt,target){evt.cancelBubble = true;});
                
                document.body.appendChild(shadowBox);
            }
            if (this.containerElm  && !CB.AJAX.isPopupLocked) {
                // now we need to hide all the other windows
                CB.AJAX.hidePopups();
                if (this.isModal){
                    var modal = CB.e('modal_background');
                    if(!modal){
                        modal = document.createElement("div");
                        modal.id = 'modal_background';
                        document.body.appendChild(modal);
                    }
                    modal.style.width = CB.Window.getScrollWidth() + 'px';
                    modal.style.height = CB.Window.getScrollHeight() + 'px';
                    modal.style.left = '0px';
                    
                    // ugly, but, this is how we have to reposition it to be seen
                    shadowBox.x = ((CB.Window.getWidth()/2) - (this.containerElm.scrollWidth/2));
                    shadowBox.y = ((CB.Window.getHeight()/2) - (this.containerElm.scrollHeight/2));
                    shadowBox.style.left = shadowBox.x + 'px';
                    shadowBox.style.top = shadowBox.y + 'px';
                    if(CB.Window.ie7 || CB.Window.gecko || CB.Window.khtml){
                        shadowBox.style.position = 'fixed';
                    }
                }else if (anchor) {
                    // if we have an anchor, then we can position based on it
                    //  otherwise, just use our current position
                    anchor.blur();
                    shadowBox.x = findX(anchor, this.containerElm, this.halign);
                    shadowBox.y = findY(anchor, this.containerElm);
                    
                    if(arguments.length == 4 && anchorOffsetX != null && anchorOffsetY != null)
                    {
                        shadowBox.x += anchorOffsetX;
                        shadowBox.y += anchorOffsetY;
                    }
                    
                    shadowBox.style.left = shadowBox.x + 'px';
                    shadowBox.style.top = shadowBox.y + 'px';
                    shadowBox.lastAnchor = anchor;
                    shadowBox.style.position = 'absolute';
                }
                
				this.onShow(options);
				this.containerElm.style.left='0px';
                shadowBox.appendChild(this.containerElm);
                
                if (!CB.Window.ie) {  // we are not in IE
                    shadowBox.style.height = (this.containerElm.scrollHeight + 1) + 'px';
                    shadowBox.style.width = (this.containerElm.scrollWidth + 4) + 'px';
                }
                else {  // we are in IE
                    shadowBox.style.height = (this.containerElm.scrollHeight + 6) + 'px';
                    shadowBox.style.width = (this.containerElm.scrollWidth + 6) + 'px';
                }
				
				iframeWrapper.style.height = (this.containerElm.offsetHeight) + 'px';
				iframeWrapper.style.width = (this.containerElm.offsetWidth) + 'px';
				iframeWrapper.style.border = 0;
				
				if (anchor) {
					iframeWrapper.style.left = findX(anchor, this.containerElm, this.halign) + 'px';
					iframeWrapper.style.top = findY(anchor, this.containerElm) + 'px';
				}
				if (!CB.Window.ie){ 
					iframeWrapper.ownerDocument.body.style.border = 0;
				} else {
					
					document.frames[iframeWrapper.id].document.onreadystatechange = function(evt){
						if ((document.frames[iframeWrapper.id].document.readyState) == 'complete'){
							document.frames[iframeWrapper.id].document.body.style.border = 0;
						}
					}
				}
				
		        
                this.containerElm.style.visibility = 'visible';
                shadowBox.style.visibility = 'visible';
				iframeWrapper.style.visibility = 'visible';
		        this.containerElm.focus();
		        var inputs = this.containerElm.getElementsByTagName('input');
		        if(inputs !== null && inputs.length > 0) {
			        if(inputs[0].style.visibility == 'visible'){
				        inputs[0].focus();
			        }
		        }
                CB.AJAX.currentVisiblePopup = this;
                CB.Window.scrollDown((shadowBox.offsetHeight + shadowBox.y - CB.Window.getScrollTop()) - CB.Window.getHeight(), 8);
                CB.EventUtils.addEventListener(document,'click',onDocumentClick);
            }
        },
        
        onShow: function(anchor, options) {
            // this function is designed to be overridden  (technically an onBeforeShow)
            // so if you have any special processing that happens when your div is opened, then
            // change onShow so that it points to a different/custom function
        },
        
        hide: function() {
            var shadowBox = CB.e('shadowAJAX');
            if (shadowBox) {
                shadowBox.style.visibility = 'hidden';
            }
			
            var iframeWrapper = CB.e('popupIframe');
			if (iframeWrapper) {
				iframeWrapper.style.visibility = 'hidden';
			}
			
            if(this.isModal){
	            var modal = CB.e('modal_background');
	            if(modal){
	                modal.style.left = '-3000px';
	            }
	        }
            
        	if (this.containerElm.style.visibility != 'hidden') {
	            this.containerElm.style.visibility = 'hidden';
		        this.containerElm.style.left='-3000px';
	            this.parentContainer.appendChild(this.containerElm);
	            this.onHide();
	        }
	        CB.EventUtils.removeEventListener(document,'click',onDocumentClick);
        },
        
        onHide: function() {
            // this function is designed to be overridden  (technically an onAfterShow)
            // so if you have any special processing that happens when your div is closed, then
            // change onHide so that it points to a different/custom function
        }
        
        // TODO: have a max height and width variable to check against and use that to determine scrolling
        // TODO: if the window resizes, then reposition yourself (this may require us to hold onto the anchor's coordinates)
    };
} ();

// Fires a callback, sending data to page, with the response handled by handler
    if(showMsg){
        if(document.title && document.title.indexOf('WAT') > -1 && document.title.indexOf('RunDeveloper') > -1){
            alert('You are using the old submitCallback method.  Please update your AJAX call to use CB.AJAX.submitCallback.  Callback sent to ' + page);
        }
    }

    var request = CB.AJAX.createRequest();
    if (request) {
        var sAjaxPrefix = '';
        if (ScriptVariables.Contains('sAjaxRelativePrefix')) {
            sAjaxPrefix = ScriptVariables.Get('sAjaxRelativePrefix');
        } else {
            sAjaxPrefix = ajaxRelativePrefix;
        }
        if (typeof sAjaxPrefix != 'undefined')
		{
			// prefix page with relative path prefix var that was inserted by MatrixPage
		    page = sAjaxPrefix + page;

			// prepare request
			request.open('POST', page, true);
			request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");

			// when the request is answered, relayResponse() will be called
			request.onreadystatechange = function() { CB.AJAX.relayResponse(request, handler); };

			// fire off the request
			request.send(data);
		}
		else
		{
			// relative path var not found, cannot correctly set path to AJAX page
			handler(false, 'Relative prefix not found (be sure to use Page.HasAjax).');
		}	
	}
	else
	{
		// request object wasn't instantiated
		handler(false, 'Unable to create request object.');
	}
}
