/*
 * Functions to disable and enable page navigation; invoked via various onclick handlers and the
 * A4J status tag. Added to prevent issues with concurrent calls to a single conversation in order
 * to address incident MNABJ-200.
 */

/**
 * Disable access to navigation elements on page.  Invoked from onclick handlers and A4J status element on pages
 * to prevent multiple server calls running concurrently on same conversation.
 */
function disableNavigation() {
	//check global to determine if page is already disabled.  This prevents issues with running the page disable
	//twice on a given request (e.g. on a double-click in the Opera browser).
	if (!isDisabled) {
		isDisabled = true;
		//disable the "floating tire selector" in the sidebar; IE 6 does not hide the select lists
		ymmoComponent.disableYMMO();
		//disable select lists on compare page if present
		var comparePageList1 = document.getElementById('compareForm:selectedFitmentNameSlot1');
		if (comparePageList1) {
			//have to disable the select lists on the compare page as IE 6 allows them to show through the layer
			comparePageList1.disabled = true;
			var comparePageList2 = document.getElementById('compareForm:selectedFitmentNameSlot2');
			if (comparePageList2) {
				comparePageList2.disabled = true;
			}
			var comparePageList3 = document.getElementById('compareForm:selectedFitmentNameSlot3');
			if (comparePageList3) {
				comparePageList3.disabled = true;
			}
		}
		//disable the DealerLocater selects if on the landing page
		if (typeof dlctrComponent != "undefined") {
			dlctrComponent.disableSelections();
		}
		//place a transparent layer over the page to block access to all navigation elements
		disablePage();
	}
}

/**
 * Enable access to navigation elements on a page.  Invoked during processing of page unload event and
 * from the A4J status tag on various pages to re-enable navigation after rendering an update to a portion of the page.
 */
function enableNavigation() {
	ymmoComponent.enableYMMO('option');
	var comparePageList1 = document.getElementById('compareForm:selectedFitmentNameSlot1');	
	if (comparePageList1) {
		//enable compare select lists on the compare page that were previously disabled
		comparePageList1.disabled = false;
		var comparePageList2 = document.getElementById('compareForm:selectedFitmentNameSlot2');
		if (comparePageList2) {
			comparePageList2.disabled = false;
		}
		var comparePageList3 = document.getElementById('compareForm:selectedFitmentNameSlot3');
		if (comparePageList3) {
			comparePageList3.disabled = false;
		}
	}
	//enable the DealerLocater selects if on the landing page
	if (typeof dlctrComponent != "undefined") {
		dlctrComponent.enableSelections("all");
	}
	enablePage();
	//clear the global that tracks if page has been disabled. See comment on disableNavigation.
	isDisabled = false;
}
/**
 * Disable all the functionality of the page by placing a transparent layer over the top of the page
 */
function disablePage() {
	var width = document.documentElement.clientWidth + document.documentElement.scrollLeft;
    var layer = document.createElement('div');
    layer.style.zIndex = 2;
    layer.id = 'transparentOverlay';
    layer.style.position = 'absolute';
    layer.style.top = '0px';
    layer.style.left = '0px';
    layer.style.height = document.documentElement.scrollHeight + 'px';
    layer.style.width = width + 'px';
    document.body.appendChild(layer);
	
	//set up a timer to display a processing message after two seconds
	msgTimer.start(2, displayProcessingMessage);
}

function enablePage(){
	msgTimer.stop();
	var layer = document.getElementById('transparentOverlay');
	if (layer) {
		document.body.removeChild(layer);
	}
	var box = document.getElementById('processingMessage');
	if (box) {
		document.body.removeChild(box);
	}
}

/**
 * Dynamically add a processing message on a third layer (over the 
 * transparent layer used to disable the page
 */
function displayProcessingMessage() {
    var div = document.createElement('div');
    div.style.zIndex = 3;
    div.id = 'processingMessage';
	div.style.position = 'absolute';

    document.body.appendChild(div);  
	
	//get width and height specified for div
	var w = parseInt(getStyle(div, 'width'));
	var h = parseInt(getStyle(div, 'height'));

	//alert("w = " + w + " h = " + h);
	
	//compute vertical position for centering div in viewport
	var top = scrollYDistance() + (windowHeight() / 2) - (h / 2);
	if (top < 0) {
		top = 0;
	}
	
	//compite horizontal position for centering div in viewport
	var left = scrollXDistance() + (windowWidth() / 2) - (w / 2);
	if (left < 0) {
		left = 0;
	}
	
	//alert("w = " + w + " left = " + left + " h = " + h + " top = " + top);
	
	//determine if message block intersects with location of the compare select lists; if so move it down
	//due to IE 6 issue - IE 6 uses a window control to render the select list, so select lists show in front
	//of all layers (z-index) - causing the select list to show through the processing message block.  Thus, we
	//check for the location of the select lists and position the message div below them if the two regions intersect
	var select1 = document.getElementById('compareForm:selectedFitmentNameSlot1');
	if (select1 && isIE()) {
		top = determineProcessingMessageTop(select1, top, h);
	}
	
	//perform same message block intersection test for the Landing page
	if (typeof dlctrComponent != "undefined" && isIE()) {
		//dlctrComponent only defined on landing page
		if (dlctrComponent.isFindTiresEnabled()) {
			//location has already been selected, so avoid placement on YMMO lists
			var element = document.getElementById('MMYO:options');
			if (element) {
				top = determineProcessingMessageTop(element, top, h);
			}			
		} else if (dlctrComponent.getSearchType() == 'CityState') {
			var element = document.getElementById('DLR:state');
			if (element) {
				top = determineProcessingMessageTop(element, top, h);
			}		
		} else if (dlctrComponent.getSearchType() == 'Zipcode') {
			var element = document.getElementById('DLR:miles');
			if (element) {
				top = determineProcessingMessageTop(element, top, h);
			}
		}
	}
	
	//alert("w = " + w + " left = " + left + " h = " + h + " top = " + top);

	//set the position of the div
	div.style.left = left + 'px';
	div.style.top = top + 'px';

    var p = document.createElement('p');
	//grab processing message text from hidden field on page
	var msgText = document.getElementById('label.processing');
	if (msgText) {
		p.innerHTML = msgText.innerHTML;
	}
    div.appendChild(p);
}

/**
 * Determine the location of the top of the processing message, based on avoiding intersection
 * with specified elementId
 * @param {Object} element
 * @param {Object} top
 * @param {Object} height
 */
function determineProcessingMessageTop(element, top, height) {
	var computedTop = top;
	
	var selectTop = pageY(element);
	var selectHeight = element.offsetHeight || parseInt(getStyle(element, 'height'));
	var selectBottom = selectTop + selectHeight;
	//alert("selectTop = " + selectTop + " selectHeight = " + selectHeight + " selectBottom = " + selectBottom);
	if ((top + height) <= selectBottom) {
		//bottom of message overlaps select list, so shift the message block below the select list
		computedTop = selectBottom + 20;
	} else if (top >= selectTop && top <= selectBottom) {
		//top of message intersects select list so shift the message block below the select list
	 	computedTop = selectBottom + 20;
	}
	return computedTop;
}

/**
 * Timer class - run a specified callback function after an elapsed number of seconds.
 */
function Timer() {
	var timerId = null;
	var timerRunning = false;
	var timeToRun = 0;
	var timerCallback = null;
	var instance = null;
	
	//constant for base time of time - set to one second
	var BASE_TIME = 1000;
	
	/**
	 * Initialize this timer
	 * @param {Object} duration - time to run in seconds
	 * @param {Object} callBack - function to call when timer has expired
	 */
	this.start = function(duration, callback) {
		timeToRun = duration;
		timerCallback = callback;
		instance = this;
		run.bindObj(msgTimer);
		run();
	}
	
	/**
	 * Start the timer
	 */
	run = function() {
		if (timeToRun == 0) {
			//time is up; stop the timer and invoke the callback function
			instance.stop();
			timerCallback();
		} else {
			timeToRun = timeToRun - 1;
			timerRunning = true;
			timerId = setTimeout("run()", BASE_TIME);
	    }
	}

	this.stop = function() {
		if (timerRunning) {
			clearTimeout(timerId);
		}
    	timerRunning = false;
		timerId = null;
	}
}

/**
 * find the height of the viewport
 */
function windowHeight() {
	var de = document.documentElement;
	return self.innerHeight || (de && de.clientHeight) || document.body.clientHeight;	
}

/**
 * find the width of the viewport
 */
function windowWidth() {
	var de = document.documentElement;
	return self.innerWidth || (de && de.clientWidth) || document.body.clientWidth;	

}

/**
 * determine how far horizontally the browser is scrolled
 */
function scrollXDistance() {
	var de = document.documentElement;
	return self.pageXOffset || (de && de.scrollLeft) || document.body.scrollLeft;
}

/**
 * determine how far vertically the browser is scrolled
 */
function scrollYDistance() {
	var de = document.documentElement;
	return self.pageYOffset || (de && de.scrollTop) || document.body.scrollTop;
}

/**
 * Get the value for a specified style for a specified element
 * 
 * @param {Object} elem The element to retrive the specified style property for
 * @param {Object} name The name of the style property to retrieve
 */
function getStyle(elem, name) {
	if (elem.style[name]) {
		return elem.style[name];
	} else if (elem.currentStyle) {
		return elem.currentStyle[name];
	} else if (document.defaultView && document.defaultView.getComputedStyle) {
		name = name.replace(/([A-Z])/g, "-$1");
		name = name.toLowerCase();
		var s = document.defaultView.getComputedStyle(elem, "");
		return s && s.getPropertyValue(name);
	} else {
		//unknown browser type
		return null;
	}
}

/**
 * Find the X (Horizontal, Left) position of an element
 * 
 * @param {Object} elem
 */
function pageX(elem) {
    var p = 0;
    while ( elem.offsetParent ) {
        p += elem.offsetLeft;
        elem = elem.offsetParent;
    }
    return p;
}

/**
 * Find the Y (Vertical, Top) position of an element
 * 
 * @param {Object} elem
 */
function pageY(elem) {
    var p = 0;
    while ( elem.offsetParent ) {
        p += elem.offsetTop;
        elem = elem.offsetParent;
    }
    return p;
}

/*
 * Add non-function code here so we don't have to pick through the entire file
 */

//global timer for disable/enablePage - used to display processing message
var msgTimer = new Timer();

//global status boolean to prevent page being disabled twice on doubleclick, etc.
var isDisabled = false;

//Ensure that transparent layer to block navigation is removed so page is not
//disabled if the user returns to it via back button
addUnloadEvent(enableNavigation);
