var _ActualRequest = null;

/**
Loads html content into a modal div (must receive a ZaveeAjaxPageContent to work)
url 		= The default URL to be used for requests to the server
config		= Identical to loadAjaxPage, except navigation is disabled
there are some extra params:
	- width: defines width for the modal
	- buttons: define a set of buttons for the modal (ej, [{text: 'OK', color: 'green(default)/red', action: FunctionPointer, closeAfterAction: true(default)/false, actionParams: [param, param2,..], type: 'cancel/normal(default)', width: 84(default)},..])
	- buttonsAlignment: defines position for buttons (default is right)
*/
function loadAjaxPageModal(url, config)
{
	if (typeof(config) == 'undefined')
	{
		config = {};
	}
	
	if (typeof(config.buttons) == 'undefined')
	{
		config.buttons = [];
	}
	
	if (typeof(config.width) == 'undefined')
	{
		config.width = undefined;
	}
	
	if (typeof(config.buttonsAlignment) == 'undefined')
	{
		config.buttonsAlignment = 'right';
	}
	
	if (typeof(config.title) == 'undefined')
	{
		config.title = '';
	}
	
	if (typeof(config.centerAfterRender) == 'undefined')
	{
		config.centerAfterRender = false;
	}
	
	if (typeof(config.closeCross) == 'undefined')
	{
		config.closeCross = true;
	}
	
	if (typeof(config.closeCrossCallback) == 'undefined')
	{
		config.closeCrossCallback = null;
	}
	
	if (config.ajaxParams == undefined)
	{
		config.ajaxParams = {};
	}
	
	var modalDiv = new ModalDiv(config.width, config.backgroundOnClick);
	
	modalDiv.AddButtons(config.buttons);
	modalDiv.SetButtonsAlign(config.buttonsAlignment);
	modalDiv.SetTitle(config.title);
	modalDiv.SetCenterAfterRender(config.centerAfterRender);
	modalDiv.SetCloseCross(config.closeCross, config.closeCrossCallback);
	
	if (typeof(config.onCompleteFn) == 'function')
	{
		var originalOnCompleteFn = config.onCompleteFn;
		
		config.onCompleteFn = function()
		{
			originalOnCompleteFn.apply();
			modalDiv.RenderContent();
		}
	}
	else
	{
		config.onCompleteFn = function () { modalDiv.RenderContent(); };
	}
	
	config.navigation 	= false;
	config.modalDiv		= modalDiv;

	loadAjaxPage(url, modalDiv.GetContentId(), config);
	
	return modalDiv;
}

/**
Carga contenido html en un elemento usando ajax (debe recibir un EYEPageContent para funcionar)

url 		= La url para hacer el pedido al servidor
elementId 	= Id del elemento donde se va a cargar el html
config		= Identico al de la funcion ajax, exepto que callbackParams esta deshabilitado	
hay algunos parametros extra de config:
	- navigation: boolean, si esta en true la pagina sera guardada en el historial de navegacion del navegador, notar que usando navigation se forzara que los parametros al ajax le lleguen por GET
	- onCompleteFn: function que sera llamada despues de que el contenido se cargue en el elemento. Si navigation ssta en true, es necesario que onCompleteFn sea el nombre de una funcion y no un puntero a la misma
	- onBeforeFn: funcion que sea llamada antes de que el contenido sea cargado en la pagina
	- overwriteHTML: booleano, si esta en true reescribe todo el contenido del elemento, por defualt esta en true (no funciona con navigation)
	- insertBefore: agrega el html al principio del target element
	- scope: scope para onComplete y onBefore
	- addUrlEmpresa: agrega la url de la empresa actual en url al pedido ajax, se pone en true automaticamente cuando se hace un navigation: true
	- forceUrlEmpresa: obliga a usar una urlempresa diferente a la de la empresa actual
*/

_pendingOnCompleteFn 		= '';
_pendingOnCompleteFnScope 	= '';

function loadAjaxPage(url, elementId, config)
{	
	if (config == undefined)
	{
		config = {};
	}

	if (config.killModal == undefined)
	{
		config.killModal = true;
	}

	if (config.overwriteHTML == undefined)
	{
		config.overwriteHTML = true;
	}

	if (config.insertBefore == undefined)
	{
		config.insertBefore = false;
	}
	else if(config.insertBefore == true)
	{
		config.overwriteHTML = false;
	}
	
	if (config.onBeforeFn != undefined)
	{
		if (config.scope == undefined)
		{
			scope = this;
		}
		else
		{
			scope = config.scope;
		}
		
		config.onBeforeFn.apply(scope);
	}
	
	if (config.navigation == true)
	{
		if (config.killModal)
		{
			KillModalDiv();
		}
		
		config.method = 'get';
		
		if (config.onCompleteFn != undefined)
		{
			if (config.scope == undefined)
			{
				scope = this;
			}
			else
			{
				scope = config.scope;
			}
			
			if (typeof(config.onCompleteFn) != 'string')
			{
				alert('ERROR: Usar navegacion requiere que no escribas una funcion asi: "function(){..}", sino que solo escribas el nombre de la funcion en un string');
				return;
			}
		}

		/*agregado para trabajacon*/
		if (typeof(config.forceUrlEmpresa) != 'undefined')
		{
			var urlEmpresa = config.forceUrlEmpresa;
		}
		else
		{
			var urlEmpresa = GetUrlEmpresa();
		}

		url = urlEmpresa + url;
		
		AddHistory(url, elementId, config.ajaxParams, config.onCompleteFn);
	}
	else
	{
		if (config.ajaxParams == undefined)
		{
			config.ajaxParams = {};
		}
		
		if (typeof(config.modalDiv) != 'undefined')
		{
			var mDiv = config.modalDiv;
		}
		else
		{
			var mDiv = undefined;
		}
		
		config.callbackParams 				= [elementId, config.onCompleteFn, config.scope, mDiv, config.overwriteHTML, config.insertBefore];
		config.scope 						= this;
		config.ajaxParams['esPedidoAjax']	= true;
		
//		ShowLoading();

		/*agregado para trabajacon*/
		if (typeof(config.addUrlEmpresa) == 'undefined')
		{
			config.addUrlEmpresa = false;
		}

		if (config.addUrlEmpresa)
		{
			if (typeof(config.forceUrlEmpresa) != 'undefined')
			{
				var urlEmpresa = config.forceUrlEmpresa;
			}
			else
			{
				var urlEmpresa = GetUrlEmpresa();
			}

			url = urlEmpresa + url;
		}
		
		ajax(url, receiveLoadAjaxPage, config);
	}
}

/**
Llama a un metodo estatico (service) en PHP que devuelve un json.

- staticMethod: el nombre del metodo estatico (ServiceTest::MiFunction)
- staticMethodParams: array de parametros que le tienen que llegar al method ['foo', 2, 'test']
- callback: funcion que sera llamada luego de recibir los datos del metodo estatico
- config: identico al de ajax
*/
function callPHPMethod(staticMethod, staticMethodParams, callback, config)
{
	if (typeof(config) == 'undefined')
	{
		config = {};
	}
	
	if (typeof(config.ajaxParams) == 'undefined')
	{
		config.ajaxParams = {};
	}
	
	if (typeof(config.callbackParams) == 'undefined')
	{
		var callbackParams = [];
	}
	else
	{
		var callbackParams = config.callbackParams;
	}
	
	config.callbackParams = [];
	
	if (typeof(config.scope) == 'undefined')
	{
		var scope = this;
	}
	else
	{
		var scope = config.scope;
	}
	
	config.scope = this;
	
	config.ajaxParams['method'] 	= staticMethod;
	config.ajaxParams['params'] 	= Ext.util.JSON.encode(staticMethodParams);
	config.method 					= 'post';
	
	config.callbackParams.unshift(callbackParams);
	config.callbackParams.unshift(scope);
	config.callbackParams.unshift(callback);
	
	var url = '/pedidosajax/callphpmethod.php';
	
	ajax(url, receivecallPHPMethod, config);
}

function receivecallPHPMethod(o, callback, scope, callbackParams)
{
	var json = eval('(' + o + ')');
	
	callbackParams.unshift(json);
	
	callback.apply(scope, callbackParams);
}

/**
Hace un pedido ajax

parametros:
	- url = la url a la que se le hara el pedido
	- callback = la funcion que sera llamada luego del pedido ajax
	- config: -- config es un objeto que contiene parametros opcionales
		- callbackParams = parametros que seran enviados a la funcion de callback (ej, [var1, var2, var3])
		- ajaxParams = parametros que seran enviados en el pedido ajax (ej, {foo: 'var', foo2: 'var2'})
		- method = el metodo HTTP por el cual sera hecho el pedido (por defecto es GET)
		- xml = buleano, si es true al callback se le enviara el objeto responseXML, si es false, se le enviara responseText
		- scope = el scope para el callback
		- form = id de un formulario, si se envia entonces todo el formulario sera enviado por ajax
		- isUpload = buleano, si es true se sabra que el formulario (enviado en form) sube archivos

ejemplos:
	simple:
		ajax('/test.php', ajaxTestCallback);

	complejo:
		ajax('/test.php', ajaxTestCallback, {callbackParams: ["param1", [1,2,3]], ajaxParams: {foo: 'var'}, method: 'POST', xml: true, scope: this, form: 'formId'});
*/
function ajax(url, callback, config)
{
	if (typeof(url) == 'undefined')
	{
		throw "url no esta definido";
	}
	
	if (typeof(callback) == 'undefined')
	{
		throw "callback no esta definido";
	}
	
	if (typeof(config) == 'undefined')
	{
		config = {};
	}
	
	if (typeof(config.ajaxParams) == 'undefined')
	{
		config.ajaxParams = {};
	}
	
	if (typeof(config.xml) == 'undefined')
	{
		config.xml = false;
	}
	
	config.ajaxParams['esPedidoAjax'] = true;

	_ActualRequest = Ext.Ajax.request(
		{
			url: url,
			success: function (o) {
				succesAjaxRequest(o, config.xml, callback, config.callbackParams, config.scope);
				_ActualRequest = null;
				
//				if (_BtnFinEjecutar != null)
//				{
//					_BtnFinEjecutar.apply(this);
//				}
			},
			failure: failAjaxRequest,
			params: config.ajaxParams,
			method: (config.method == undefined) ? 'GET' : config.method.toUpperCase(),
			form: config.form,
			isUpload: config.isUpload
		}
	);
}

function AbortActualAjaxRequest()
{
	if (_ActualRequest != null)
	{
		Ext.Ajax.abort(_ActualRequest.tId);
		
		_ActualRequest = null;
	}
}

function receiveLoadAjaxPage(json, elementId, onCompleteFn, scope, mDiv, overwriteHTML, insertBefore)
{
	
	var json = eval('(' + json + ')');
	
	if ((typeof(json.reDoModalDivButtons) != 'undefined') && (typeof(mDiv) == 'object'))
	{
		mDiv.RemoveButtons();
		
		if (json.reDoModalDivButtons.length > 0)
		{
			mDiv.AddButtons(json.reDoModalDivButtons);
		}
	}
	
	if ((typeof(json.overridePage) != 'undefined'))
	{
		location.href = json.overridePage;
		return;
	}
	
	if (typeof(json.forceDataCompletion) == 'boolean')
	{
		if (json.forceDataCompletion)
		{
			LoadDataCompletionPopUp();
		}
	}

	if (typeof(json.pageTitle) == 'string')
	{
		if (json.pageTitle != '')
		{
			document.title = json.pageTitle;
		}
	}
	
	var targetElement = document.getElementById(elementId);
	
	if (targetElement == null)
	{
		throw 'El elemento (targetElement) no existe';
	}
	
	if (typeof(targetElement) != 'undefined')
	{
		if (overwriteHTML == true)
		{
			targetElement.innerHTML = json.html;
		}
		else
		{
			if (insertBefore)
			{
				targetElement.innerHTML = json.html + targetElement.innerHTML;
			}
			else
			{
				targetElement.innerHTML += json.html;
			}
		}
		
		if (json.jslibraries.length > 0)
		{
			var _libsToLoad = json.jslibraries.length;
			
			for (i = 0; i < json.jslibraries.length; i++)
			{
				AddScript(json.jslibraries[i].lib, json.jslibraries[i].force, function()
				{
					_libsToLoad--;
					
					if (_libsToLoad == 0)
					{
						if (onCompleteFn != undefined)
						{
							if (scope == undefined)
							{
								scope = this;
							}
							
							if (typeof(onCompleteFn) != 'string')
							{
								onCompleteFn.apply(scope);
							}
							else
							{
								eval(onCompleteFn + '();');
							}
						}
						
						eval(json.jsToExcecute);
					}
				});
			}
		}
		else
		{
			if (onCompleteFn != undefined)
			{
				if (scope == undefined)
				{
					scope = this;
				}
				
				if (typeof(onCompleteFn) != 'string')
				{
					onCompleteFn.apply(scope);
				}
				else
				{
					eval(onCompleteFn + '();');
				}
			}
			
			eval(json.jsToExcecute);
		}
		
		for (i = 0; i < json.stylesheets.length; i++)
		{
			AddStyleSheet(json.stylesheets[i]);
		}
	}
	else
	{
		ForceCompleteHistoryLoad();
	}
	
//	HideLoading();
	
	if (typeof(OcultarTodasSubBotoneras) == 'function')
	{
		OcultarTodasSubBotoneras();
	}
}

function succesAjaxRequest(o, xml, callback, callbackParams, scope)
{
	if (xml == true)
	{
		var content = o.responseXML;
	}
	else
	{
		var content = o.responseText;
	}

	//reviso si hay que redirigir
	if (xml == false)
	{
		var json = eval('(' + content + ')');
	
		if ((typeof(json.overridePage) != 'undefined'))
		{
			location.href = json.overridePage;
			return;
		}
	}
	
	if (scope == undefined)
	{
		scope = this;
	}
	
	if (callbackParams == undefined)
	{
		callbackParams = [];
	}
	
	callbackParams.unshift(content);

	callback.apply(scope, callbackParams);
}

function failAjaxRequest()
{
	_ActualRequest = null;
	
	throw "ajax load error";
}

/*
Adds a Js Script to actual page
*/
function AddScript(path, force, callback)
{
	var isLoaded = ScriptIsLoaded(path);

	if ((typeof(isLoaded) == 'object') && (force == true))
	{
		isLoaded.parentNode.removeChild(isLoaded);
		
		isLoaded = false;
	}
	
	if (!isLoaded)
	{
		var scriptTag = document.createElement('script');
		scriptTag.setAttribute('type', 'text/javascript');
		scriptTag.setAttribute('src', path);

		var headLoc = document.getElementsByTagName('head').item(0);
		
		var done = false;
		
		scriptTag.onload = scriptTag.onreadystatechange = function()
		{
			if ( !done && (!this.readyState || this.readyState == "loaded" || this.readyState == "complete") )
			{
				done = true;
				
				if (typeof(callback) == 'function')
				{
					callback();
				}
				
				/* handle memory leak in IE */
				scriptTag.onload = scriptTag.onreadystatechange = null;
			}
		};
		
		headLoc.appendChild(scriptTag);
	}
	else
	{
		if (typeof(callback) == 'function')
		{
			callback();
		}
	}
}

function ScriptIsLoaded(path)
{
	var scripts = document.getElementsByTagName('script');
	
	for (x = 0; x < scripts.length; x++)
	{
		src = scripts[x].getAttribute('src');
		
		if (src != undefined)
		{
			if (src == path)
			{
				return scripts[x];
			}
		}
	}
	
	return false;
}

/*
Adds a CSS Stylesheet to actual page
*/

function AddStyleSheet(path)
{
	isLoaded = StyleSheetIsLoaded(path);
	
	if (!isLoaded)
	{
		styleSheetTag = document.createElement('link');
		styleSheetTag.setAttribute('rel', 'stylesheet');
		styleSheetTag.setAttribute('type', 'text/css');
		styleSheetTag.setAttribute('href', path);
		
		headLoc = document.getElementsByTagName('head').item(0);
		headLoc.appendChild(styleSheetTag);
	}
}

function StyleSheetIsLoaded(path)
{
	styleSheets = document.getElementsByTagName('link');
	
	for (x = 0; x < styleSheets.length; x++)
	{
		src = styleSheets[x].getAttribute('href');
		
		if (src != undefined)
		{
			if (src == path)
			{
				return true;
			}
		}
	}
	
	return false;
}

var keyStr = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

function encode64(input)
{
	var output = "";
	var chr1, chr2, chr3;
	var enc1, enc2, enc3, enc4;
	var i = 0;
	
	do
	{
		chr1 = input.charCodeAt(i++);
		chr2 = input.charCodeAt(i++);
		chr3 = input.charCodeAt(i++);
		
		enc1 = chr1 >> 2;
		enc2 = ((chr1 & 3) << 4) | (chr2 >> 4);
		enc3 = ((chr2 & 15) << 2) | (chr3 >> 6);
		enc4 = chr3 & 63;
		
		if (isNaN(chr2))
		{
			enc3 = enc4 = 64;
		}
		else if (isNaN(chr3))
		{
			enc4 = 64;
		}
		
		output = output + keyStr.charAt(enc1) + keyStr.charAt(enc2) + keyStr.charAt(enc3) + keyStr.charAt(enc4);
	} while (i < input.length);
	
	return output;
}

function decode64(input)
{
	var output = "";
	var chr1, chr2, chr3;
	var enc1, enc2, enc3, enc4;
	var i = 0;
	
	// remove all characters that are not A-Z, a-z, 0-9, +, /, or =
	input = input.replace(/[^A-Za-z0-9\+\/\=]/g, "");
	
	do
	{
		enc1 = keyStr.indexOf(input.charAt(i++));
		enc2 = keyStr.indexOf(input.charAt(i++));
		enc3 = keyStr.indexOf(input.charAt(i++));
		enc4 = keyStr.indexOf(input.charAt(i++));
		
		chr1 = (enc1 << 2) | (enc2 >> 4);
		chr2 = ((enc2 & 15) << 4) | (enc3 >> 2);
		chr3 = ((enc3 & 3) << 6) | enc4;
		
		output = output + String.fromCharCode(chr1);
		
		if (enc3 != 64)
		{
			output = output + String.fromCharCode(chr2);
		}
		
		if (enc4 != 64)
		{
			output = output + String.fromCharCode(chr3);
		}
	} while (i < input.length);
	
	return output;
}
