//***
//* 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){
	            if(typeof ajaxRelativePrefix != 'undefined'){
		            // prefix page with relative path prefix var that was inserted by MatrixPage
		            page = ajaxRelativePrefix + 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);
	            }
	            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.');
            }
        },
        
        // 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.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,
        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.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
function submitCallback(data, page, handler, showMsg)
{
    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)
	{
		if(typeof ajaxRelativePrefix != 'undefined')
		{
			// prefix page with relative path prefix var that was inserted by MatrixPage
			page = ajaxRelativePrefix + 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.');
	}
}