
	/* loadingIndicator */

	function loadingIndicator() {}

	loadingIndicator.prototype.show = function(parentElement)
	{
		this.element = parentElement.ownerDocument.createElement('div');
		this.element.className = 'loadingIndicator';
		this.element.style.left = parentElement.offsetLeft + parentElement.offsetWidth/2 + 'px';
		this.element.style.top = parentElement.offsetTop + parentElement.offsetHeight/2 + 'px';
		parentElement.parentNode.insertBefore(this.element, parentElement.nextSibling);
	}

	loadingIndicator.prototype.hide = function()
	{
		this.element.parentNode.removeChild(this.element);
	}

	function importDocumentMedia(sourceDocument)
	{
		$(sourceDocument).find('head script').each( function() {
			if($(document).find("head script[src='"+ this.getAttribute('src') +"']").length == 0)
				$(document).find("head").append('<script src="'+ this.getAttribute('src') +'" type="'+ this.getAttribute('type') +'"/>');
		})

		$(sourceDocument).find('head link').each( function() {
			if($(document).find("head link[href='"+ this.getAttribute('href') +"']").length == 0)
				$(document).find("head").append('<link media="'+ this.getAttribute('media') +'" href="'+ this.getAttribute('href') +'" type="'+ this.getAttribute('type') +'" rel="'+ this.getAttribute('rel') +'"/>');
		})
	}

	function ajaxUpdateComponent(component, link)
	{
		if(link == undefined) link = new ajaxLink(window.location.href);

		if(typeof component == 'string')
		{
			var element = link.a;
			if(element == undefined) element = link.form;
			var rootNode = document.documentElement;
			if(element != undefined)
			{
				rootNode = $(element).parents(".dialog:first").get(0);
				if(!rootNode) rootNode = element.ownerDocument.documentElement;
			}
		
			var componentId = component;
			var sourceComponent = $(rootNode).find("[component='"+componentId+"']").andSelf().get(0);
					
		}
		else
		{
			var sourceComponent = component;
			var componentId = sourceComponent.getAttribute('component');
		}

		if(link.submit != undefined) $(link.submit).attr('disabled', 'disabled');
		
		var indicator = new loadingIndicator();
		indicator.show(sourceComponent);

		$(sourceComponent).fadeOut('medium');

		var success = function(loadedDocument)
		{
			if(link.submit != undefined) $(link.submit).removeAttr('disabled');
			importDocumentMedia(loadedDocument);
			var component = $(loadedDocument).find("[component='"+ componentId +"']");
			indicator.hide();
			var container = sourceComponent.parentNode;
			$(sourceComponent).replaceWith(component.toXML());
			$("[component='"+ componentId +"']", container).hide().fadeIn('fast');
			
			$(document).trigger('update');
		}

		var error = function()
		{
			if(link.submit != undefined) $(link.submit).removeAttr('disabled');
			$(sourceComponent).fadeIn('fast');
			indicator.hide();
		}

		link.setParameter('componentFilter', componentId, false);
		link.setParameter('outputMimeType', 'application/xhtml+xml', true);
		link.loadXml({success: success, error: error});

		return true;
	}

	function ajaxUpdate(link)
	{
		var targetComponentId = link.getParameter('targetComponent');

		if(targetComponentId != undefined && targetComponentId.length)
		{
			return ajaxUpdateComponent(targetComponentId, link)
		}	

		return false;
	}

	function ajaxOpen(link)
	{
		var targetComponentId = link.getParameter('targetComponent');
		if(targetComponentId != undefined && targetComponentId.length)
		{
			var win = new dialog(undefined, link.getParameter('window.mode'));
			win.autoDestroy = true;
			win.href = link.assembleRef();
			win.open();

			switch($('html').attr('lang'))
			{
				case 'ru':
					win.setContent('<div class="message">Содержимое загружается. Пожалуйста, подождите...</div>');
					break;

				case 'en':
					win.setContent('<div class="message">Content loading in process. Please wait, this may take a few seconds...</div>');
			}

			var indicator = new loadingIndicator();
			indicator.show(win.contentContainer);

			link.setParameter('componentFilter', targetComponentId, false);
			link.setParameter('outputMimeType', 'application/xhtml+xml', true);
			var loadedDocument = link.loadXml();
			importDocumentMedia(loadedDocument);
			var component = $(loadedDocument).find("[component='"+ targetComponentId +"']");
			indicator.hide();

			win.setContent(component.toXML());

			$(win.contentContainer).hide().fadeIn('fast').slideDown('fast');
			$(document).trigger('update');

			return true;
		}
		return false;
	}

	function ajaxLoad(link, currentRef)
	{
		if(currentRef == undefined) currentRef = window.location.href;

		var oldLink = new ajaxLink(currentRef);
		try
		{
			if(link.protocol == 'http:' && oldLink.host == link.host)
			{
				var target = link.getParameter('target');
				if(target == undefined) target = oldLink.path != link.path ? 'new' : 'this';
				return !(target == 'new' ? ajaxOpen(link) : ajaxUpdate(link));
			}

		}
		catch(e) {
			alert('AJAX handler: ' + e.message)
		}

		return true;
	}

	function ajaxHandleLink(a)
	{
		var win = $(a).parents(".dialog:first").get(0);
		var currentRef = win && win.dialog ? win.dialog.href : window.location.href;

		var link = new ajaxLink();
		link.assignA(a);
		return ajaxLoad(link, currentRef);
	}

	function ajaxHandleFormSubmit(submit)
	{
		var form = $(submit).parents("form:first").get(0);

		var win = $(form).parents(".dialog:first").get(0);
		var currentRef = win && win.dialog ? win.dialog.href : window.location.href;

		var link = new ajaxLink();
		link.assignForm(form, submit);

		var oldLink = new ajaxLink(currentRef);
		if(link.protocol == 'http:' && oldLink.host == link.host && oldLink.path == link.path)
			link.setParameter('targetComponent', $(form).parents("[component]:first").andSelf().filter("[component]:last").attr('component'), false);

		return ajaxLoad(link, currentRef);
	}

	function ajaxLinkHandler(event)
	{
		if(!ajaxHandleLink(this)) event.preventDefault();
	}

	function ajaxFormSubmitHandler(event)
	{
		if(!$(this).parents("form:first").get(0).target)
		{
			if(!ajaxHandleFormSubmit(this)) event.preventDefault();
		}
	}
	
	function ajaxInit()
	{
		$("form :submit:not([onclick]), form :image:not([onclick])").live('click', ajaxFormSubmitHandler);
		$("a:not([onclick])").live('click', ajaxLinkHandler);

		$("body").ajaxStart(function(){
			$(this).css('cursor', 'progress');
		});

		$("body").ajaxStop(function(){
			$(this).css('cursor', 'auto');
		});

		$(document).trigger('update');
	}

	$(document).ready(ajaxInit);

	// TOFIX:
	// 1. concurent requests
