/**
 * Ajax Implements
 * Criado em 23/09/2006
 *
 * @author Daniel Araujo
 * 
 * Depends:
 *	core.js
 *	util.js
 */
window.onload = function() {
	initializeAjaxForms();
	invokeHistoryBookmark(getIframeRegisterManager());
};
window.onunload = function() {
	if (!self.screenTop) {
		if (document.body.clientHeight == 0)
			clearHistory();
	} else if (self.screenTop > 8000) {
		clearHistory();
	}
};

/**
 * Takes a form object and returns a JavaScript object containing the form field
 * names and values as would be submitted to the server.  Correctly handles
 * radio, checkboxes, single and multi selects - including them in the request
 * only if one or more values has been specified. Excludes button types
 * (submit, reset, button)
 *
 * @return a JavaScript object with a property for each form field to be
 *         submitted. The value of each property is an Array containing one or
 *         more values to be submitted.
 */
function getFormValuesAsMap(form) {
	
	var params = new Object();
	var inputs = form.elements;
	for (var i = 0; i < inputs.length; i++) {
		var input = inputs[i];

		if (input.type == 'radio' || input.type == 'checkbox') {
			// For radios and checkboxes, include them only if checked
			if (input.checked == true) {
                if (params[input.name] == null) 
                	params[input.name] = new Array();
                params[input.name].push(input.value);
			}
		} else if (input.type == 'select-multiple') {
			// For multi-selects we have to check each value
			for (var j = 0; j < input.options.length; j++) {
				if (input.options[j].selected == true) {
                    if (params[input.name] == null) 
                    	params[input.name] = new Array();
                    params[input.name].push(input.options[j].value);
				}
			}
		} else if (input.type == 'submit' || input.type == 'button' || input.type == 'reset') {
			// Don't include button types in the submit
		} else {
			// Include any other type as a straight name=value
            if (params[input.name] == null) 
            	params[input.name] = new Array();
            params[input.name].push(input.value);
		}
	}

    return params;
}

/**
 * Takes a form object and returns a query string containing all the fields
 * that would be submitted to the server. See getFormValuesAsMap(form) for more
 * details on what's included. Each value is escaped before being included in
 * the query string.
 *
 * @return a query string. The query string will always start with an ampersand.
 */
function getFormValuesAsQueryString(form) {
    
    var params = this.getFormValuesAsMap(form);
    var queryString = '';

    for (var name in params) {
        var values = params[name];
        for (var i = 0; i < values.length; i++) {
            queryString += '&' + name + '=' + escape(values[i]);
        }
    }

    return queryString;
}

/**
 * Gets a new XMLHttpRequest object.
 */
function getXmlHttpRequest() {
	try {
		return new XMLHttpRequest(); 
	} catch (ex) {
		try {
			return new ActiveXObject('Msxml2.XMLHTTP.4.0');
		} catch (ex1) {
			try {
				return new ActiveXObject('Msxml2.XMLHTTP'); 	
			} catch(ex2) {
				return new ActiveXObject('Microsoft.XMLHTTP');
			}
        }
    }
}

/**
 * Utility method to make a request to the supplied URL and invoked hte callback
 * function, passing it the XMLHttpRequest.
 */
function fetchFromUrl(url, callbackFunction, method) {
    
    try {
   		netscape.security.PrivilegeManager.enablePrivilege('UniversalBrowserRead');
    } catch (e) {}
	
	var xmlHttpRequest = this.getXmlHttpRequest();
    xmlHttpRequest.onreadystatechange = function() {
        if (xmlHttpRequest.readyState == 4 && callbackFunction != null) {
            callbackFunction(xmlHttpRequest);
        }
    };

    if (method == null)
        method = 'GET';
		
	var charLink = '?';
	if (url.contains('?'))
		charLink = '&';	
	url += charLink + 'nocache=' + (new Date().getTime());
	var queryString = url.substring(url.indexOf('?') + 1);
	url = url.substring(0, url.indexOf('?'));

	xmlHttpRequest.open(method, url, true, '', '');
	xmlHttpRequest.send(queryString);
	
    return xmlHttpRequest;
}

/**
 * Initialize a implements form to submit Ajax calling.
 */
function initializeAjaxForms() {
	
	var forms = document.getElementsByTagName('FORM');
	for (var i = 0; i < forms.length; i++) {
		if (forms[i].getAttribute("useAjax") == 'true')
			forms[i].onsubmit = function() {
				var queryString = getFormValuesAsQueryString(this);
				var url = this.action;
				var charLink = '?';
				if (url.contains('?'))
					charLink = '&';
				url += charLink + queryString.substring(1);
				var ajaxTarget = document.getElementById(this.getAttribute('ajaxTarget'));
				var callbackFunction = function(xmlHttpRequest) { 
					defaultAjaxSubmit(xmlHttpRequest, ajaxTarget);
				};
				if (this.getAttribute('callbackFunction') != null)
					callbackFunction = window[this.getAttribute('callbackFunction')];
				fetchFromUrl(url, callbackFunction, this.method);
				return false;
			};
	}
}

/**
 * Default function for Ajax form submit.
 */
function defaultAjaxSubmit(xmlHttpRequest, target) {
	target.innerHTML = xmlHttpRequest.responseText;
	initializeAjaxForms();
}

/**
 * Register bookmark implementation.
 */
var registerManagerPath = '';
var isRegisterHistory = true;
var invokeHistoryUserFunction = null;
 
/**
 * Register a ajax calling history page.
 */
function registerBookmark(url, target, method) {
	isRegisterHistory = true;
	var hash = new Date().getTime();
	createCookie('ajaxHistoryHash' + hash, 'target=' + target + '&method=' + method + '&url=' + url, 1);
	var linkHistory = document.createElement('DIV');
	linkHistory.style.display = 'none';
	linkHistory.innerHTML = '<form action="' + registerManagerPath + 'ajaxHashBookmark.html#' + 
		hash + '" method="get" target="ajaxBookmarkRegisterFrame">' + 
		'<input type="type" name="hash" value="' + hash + '" />' + 
		'</form>';
	document.body.appendChild(linkHistory);
	linkHistory.childNodes[0].submit();
	document.body.removeChild(linkHistory);
}

/**
 * Return true on refresh page.
 */
function isReloadPage() {
	return (document.cookie.contains('ajaxHistoryHash'));
}

/**
 * Invoke a history.
 */ 
function invokeHistoryBookmark() {
	var registerManager = getIframeRegisterManager();
	if (registerManager != null && !isRegisterHistory) {
		if (isReloadPage()) {
			var hash = registerManager.contentWindow.document.location.hash.substring(1);
			var ajaxHistory = readCookie('ajaxHistoryHash' + hash);
			if (ajaxHistory != null) {
				var target = ajaxHistory.substring(7, ajaxHistory.indexOf('&method='));
				if (document.getElementById(target) != null) {
					var method = ajaxHistory.substring(ajaxHistory.indexOf('&method=') + 8, ajaxHistory.indexOf('&url='));
					var url = ajaxHistory.substring(ajaxHistory.indexOf('&url=') + 5);
					var callbackFunction = function(xmlHttpRequest) {
						document.getElementById(target).innerHTML = xmlHttpRequest.responseText;
						if (invokeHistoryUserFunction != null)
							invokeHistoryUserFunction();
					};
					fetchFromUrl(url, callbackFunction, method);
				}
			}
		}
	} else {
		isRegisterHistory = false;
	}
}

/**
 * Clear a history on close browser.
 */
function clearHistory() {
	var cookies = document.cookie.split(';');
	for (var i = 0; i < cookies.length; i++) {
		var cookie = cookies[i];
		var historyId = cookie.substring(0, cookie.indexOf('='));
		if (historyId.contains('ajaxHistoryHash'))
			eraseCookie(historyId);
	}
}

/**
 * Create a iframe register manager.
 */
function createAjaxRegisterManager(path) {
	registerManagerPath = path;
	document.write('<iframe name="ajaxBookmarkRegisterFrame" style="display: none;" ' + 
				   'onload="javascript: invokeHistoryBookmark();"></iframe>');
}

/**
 * Return a object iframe register manager.
 */
function getIframeRegisterManager() {
	var frames = document.getElementsByTagName('IFRAME');
	if (frames.length > 0) {
		var registerManager = null;
		for (var i = 0; i < frames.length; i++) {
			if (frames[i].name == 'ajaxBookmarkRegisterFrame') {
				registerManager = frames[i];
				break;
			}
		}
		if (registerManager != null && registerManager.contentWindow != null && 
				registerManager.contentWindow.document != null && 
				registerManager.contentWindow.document.location.hash != '')
			return registerManager;
		else
			return null;
	}
}

/**
 * Return a current url from de history register manager.
 */
function getCurrentHistoryUrl() {
	var registerManager = getIframeRegisterManager();
	if (registerManager != null) {
		var hash = registerManager.contentWindow.document.location.hash.substring(1);
		var ajaxHistory = readCookie('ajaxHistoryHash' + hash);
		if (ajaxHistory != null)
			return ajaxHistory.substring(ajaxHistory.indexOf('&url=') + 5);
	}
	return null;
}