// Main AJAX classs
function Request() {}

Request.timeout = 60000; //60 seconds
Request.method = 'GET';
Request.headers = new Array();
Request.params = null;

Request.makeRequest = function(p_url, p_busyReq, p_progId, p_successCallBack, p_errorCallBack, p_pass, p_object) {
	//p_url: the web service url
	//p_busyReq: is a request for this object currently in progress?
	//p_progId: element id where progress HTML should be shown
	//p_successCallBack: callback function for successful response
	//p_errorCallBack: callback function for erroneous response
	//p_pass: string of params to pass to callback functions
	//p_object: object of params to pass to callback functions

	if (p_busyReq) return;
	var req = Request.getRequest();
	if (req != null) {
		p_busyReq = true;
		Request.showProgress(p_progId);
		req.onreadystatechange = function() {
			if (req.readyState == 4) {
				p_busyReq = false;
				window.clearTimeout(toId);
				try {
					if (req.status == 200) {
	//					preg_print_pre(req)
						p_successCallBack(req, p_pass, p_object);
					} else {
						p_errorCallBack(req, p_pass, p_object);
					}
					Request.hideProgress(p_progId);
				}
				catch (e) {
//					alert('AJAX error')
				}
			}
		}
		var $ajax_mark = (p_url.indexOf('?') ? '&' : '?') + 'ajax=yes';
		req.open(Request.method, p_url + $ajax_mark, true);

		if (Request.method == 'POST') {
			Request.headers['Content-type'] = 'application/x-www-form-urlencoded';
			Request.headers['referer'] = p_url;
		}
		else {
			Request.headers['If-Modified-Since'] = 'Sat, 1 Jan 2000 00:00:00 GMT';
		}

		Request.sendHeaders(req);
		if (Request.method == 'POST') {
			req.send(Request.params);
			Request.method = 'GET'; // restore method back to GET
		}
		else {
			req.send(null);
		}

		var toId = window.setTimeout( function() {if (p_busyReq) req.abort();}, Request.timeout );
	}
}

Request.processRedirect = function($request, $url_params) {
	var $match_redirect = new RegExp('^#redirect#(.*)').exec($request.responseText);

	if ($match_redirect != null) {
		// redirect to external template requested
		if ($url_params != '') {

			window.location.href = $match_redirect[1] + '?' + $url_params;
		}
		else {
			window.location.href = $match_redirect[1]
		}
		return true;
	}
	return false;
}
Request.sendHeaders = function($request) {
	for (var $header_name in Request.headers) {
		if (typeof Request.headers[$header_name] == 'function') {
			continue;
		}
		$request.setRequestHeader($header_name, Request.headers[$header_name]);
	}
	Request.headers = new Array(); // reset header afterwards
}

Request.getRequest = function() {
	var xmlHttp;
	try { xmlHttp = new ActiveXObject('MSXML2.XMLHTTP'); return xmlHttp; } catch (e) {}
	try { xmlHttp = new ActiveXObject('Microsoft.XMLHTTP'); return xmlHttp; } catch (e) {}
	try { xmlHttp = new XMLHttpRequest(); return xmlHttp; } catch(e) {}
	return null;
}

Request.showProgress = function(p_id) {
	if (p_id != '') {
		Request.setOpacity(20, p_id);

		if (!document.getElementById(p_id + '_progress')) {
			document.body.appendChild(Request.getProgressObject(p_id));
		}
		else {
			var $progress_div = document.getElementById(p_id + '_progress');
			$progress_div.style.top = getRealTop(p_id) + 'px';
			$progress_div.style.height = document.getElementById(p_id).clientHeight;
			$progress_div.style.display = 'block';
		}
//		document.getElementById(p_id).innerHTML = Request.getProgressHtml();
	}
}

Request.hideProgress = function(p_id) {
	if (p_id != '') {
		document.getElementById(p_id + '_progress').style.display = 'none';
		Request.setOpacity(100, p_id);
	}
}

Request.setOpacity = function (opacity, id) {
	var elem = typeof(id)=='string' ? document.getElementById(id) : id;
    var object = elem.style;
    object.opacity = (opacity / 100);
    object.MozOpacity = (opacity / 100);
    object.KhtmlOpacity = (opacity / 100);
    object.filter = "alpha(opacity=" + opacity + ")";
}

Request.getProgressHtml = function() {
	return "<p class='progress'>" + Request.progressText + "<br /><img src='" + Request.progressImage + "' align='absmiddle' width='100' height='7' alt='" + Request.progressText + "'/></p>";
}

Request.getProgressObject = function($id) {
	var $div = document.createElement('DIV');
	var $parent_div = document.getElementById($id);

	$div.id = $id + '_progress';

	$div.style.width = $parent_div.clientWidth + 'px';
	$div.style.height = '150px'; // default height if div is empty (first ajax request for div)
	$div.style.left = getRealLeft($parent_div) + 'px';
	$div.style.top = getRealTop($parent_div) + 'px';
	$div.style.position = 'absolute';

	$div.style.display = getRealTop($parent_div)/*document.getElementById($id).clientHeight*/ > 0 ? 'block' : 'none';

	$div.innerHTML = '<table style="width: 100%; height: 100%;"><tr><td style="text-align: center;">'+Request.progressText+'<br /><img src="'+Request.progressImage+'" align="absmiddle" width="100" height="7" alt="'+escape(Request.progressText)+'" /></td></tr></table>';
	return $div;
}
Request.getErrorHtml = function(p_req) {
	//TODO: implement accepted way to handle request error
	return '[status: ' + p_req.status + '; status_text: ' + p_req.statusText + '; responce_text: ' + p_req.responseText + ']';
}

Request.serializeForm = function(theform) {
	if (typeof(theform) == 'string') {
		theform = document.getElementById(theform);
	}

	var els = theform.elements;
	var len = els.length;
	var queryString = '';

	Request.addField = function(name, value) {
		if (queryString.length > 0) queryString += '&';
		queryString += encodeURIComponent(name) + '=' + encodeURIComponent(value);
	};

	for (var i = 0; i<len; i++) {
		var el = els[i];
    	if (el.disabled) continue;

		switch(el.type) {
			case 'text':
			case 'password':
			case 'hidden':
			case 'textarea':
          		Request.addField(el.name, el.value);
				break;

			case 'select-one':
				if (el.selectedIndex >= 0) {
            		Request.addField(el.name, el.options[el.selectedIndex].value);
          		}
          		break;

			case 'select-multiple':
				for (var j = 0; j < el.options.length; j++) {
            		if (!el.options[j].selected) continue;
              		Request.addField(el.name, el.options[j].value);
          		}
          		break;

			case 'checkbox':
			case 'radio':
          		if (!el.checked) continue;
            	Request.addField(el.name,el.value);
          		break;
      	}
	}
	return queryString;
};

function RatingManager ($url) {
	this.Url = $url;
	this.BusyRequest = false;
}

RatingManager.prototype.makeVote = function ($vote, $prefix, $id, $size) {
	var $url = this.Url.replace('#PREFIX#', $prefix).replace('#VOTE#', $vote).replace('#ID#', $id).replace('#SIZE#', $size);

	Request.makeRequest($url, this.BusyRequest, '', this.successCallback, this.errorCallback, [$vote, $prefix, $id], this);
}

RatingManager.prototype.successCallback = function ($request, $params, $object) {
    var response = $request.responseText;

    if (response.substring(0, 5) == '@err:') {
    	alert(response.substring(5));
    	return ;
    }

    document.getElementById('page_rating_' + $params[2]).innerHTML = response;
}


RatingManager.prototype.errorCallback = function($request, $params, $object) {
	alert('AJAX Error; class: RatingManager; ' + Request.getErrorHtml($request));
}

function PageManager ($progressText, $progressImage) {
	this.ContentDivId = '';
	this.BusyRequest = false;
	Request.progressText = $progressText;
	Request.progressImage = $progressImage;
}

PageManager.prototype.changePage = function ($url, $div_id, $hide_loading) {
	this.ContentDivId = $div_id;
	Request.makeRequest($url, this.BusyRequest, $hide_loading? '' : this.ContentDivId, this.successCallback, this.errorCallback, '', this);
}

PageManager.prototype.successCallback = function ($request, $params, $object) {
	Request.processRedirect($request, $object.RedirectParams);
	 var response = $request.responseText;
    if (response.substring(0, 5) == '@err:') {
    	alert(response.substring(5));
    	return ;
    }
    document.getElementById($object.ContentDivId).innerHTML = response;
}

PageManager.prototype.setSubmitForm = function ($form_id, $div_id) {
	this.ContentDivId = $div_id;
	var $kf = document.getElementById($form_id);
	Request.params = Request.serializeForm($kf);
	Request.method = $kf.method.toUpperCase();
	this.BusyRequest = false;
	Request.makeRequest($kf.action, this.BusyRequest, this.ContentDivId, this.successCallback, this.errorCallback, this.ContentDivId, this);
}

PageManager.prototype.errorCallback = function($request, $params, $object) {
	alert('AJAX Error; class: PageManager; ' + Request.getErrorHtml($request));
}

// ToolTip
var offsetX = 0;
var offsetY = 20;
var toolTipSTYLE = '';

function initToolTips() {
	toolTipSTYLE = document.getElementById('toolTipLayer').style;
	toolTipSTYLE.visibility = 'visible';
	toolTipSTYLE.display = 'none';

	document.onmousemove = moveToMouseLoc;
}

function toolTip() {
	if (arguments.length < 1) {
		// hide
		toolTipSTYLE.display = 'none';
	} else {
		// show
		if (document.all) {
			moveToMouseLoc();
		}
		else {
			moveToMouseLoc(document);
		}

		if (arguments[0].match(/event:([\d]+)/)) {
			// content via ajax request
			document.getElementById('toolTipLayer').innerHTML = Request.progressText;
			toolTipSTYLE.display = 'block';
			aAjaxEventManager.getTooltip(RegExp.$1);
		}
		else {
			// direct content
			document.getElementById('toolTipLayer').innerHTML = arguments[0];
			toolTipSTYLE.display = 'block';
		}
	}
}

function moveToMouseLoc(e) {
	if (document.all) {
		x = event.x + document.body.scrollLeft;
		y = event.y + document.body.scrollTop;
	}
	else {
		x = e.pageX;
		y = e.pageY;
	}

	toolTipSTYLE.left = x + offsetX;
	toolTipSTYLE.top = y + offsetY;

	return true;
}

// AjaxEventManager
function AjaxEventManager($url, $tooltip_id) {
	this.URL = $url;
	this.toolTipID = $tooltip_id;
	this.BusyRequest = false;

	this.toolTipCache = [];
	addLoadEvent(initToolTips);
}

AjaxEventManager.prototype.getTooltip = function($event_id) {
	// cache locally, when possible
	if (this.toolTipCache[$event_id]) {
		this.setTooltip(this.toolTipCache[$event_id]);
		return ;
	}

	var $url = this.URL.replace('#ID#', $event_id).replace('#EVENT#', 'OnGetEventTooltip').replace('#FILTER_TYPE#', '');
	Request.makeRequest($url, this.BusyRequest, '', this.successCallback, this.errorCallback, ['tooltip', $event_id], this);
}

AjaxEventManager.prototype.setTooltip = function($text) {
	document.getElementById(this.toolTipID).innerHTML = $text;
}


AjaxEventManager.prototype.successCallback = function($request, $params, $object) {
	switch ($params[0]) {
		case 'tooltip':
			$object.setTooltip($request.responseText);
			$object.toolTipCache[ $params[1] ] = $request.responseText;
			break;

		case 'filter_values':
			var $control = document.getElementById('filter_value');
			$object.ProcessXMLNode($request.responseXML, $control, $params[2]);
			break;
	}
}

AjaxEventManager.prototype.errorCallback = function($request, $params, $object) {
	alert('AJAX Error; class: AjaxEventManager; ' + Request.getErrorHtml($request));
}

AjaxEventManager.prototype.ProcessXMLNode = function($node, $dst_field, $empty_title) {
	for (var i = 0; i < $node.childNodes.length; i++) {
		var $child = $node.childNodes.item(i);
		switch ($child.tagName) {
			case 'option':
				var opt_value = $child.getAttribute('value');
				var title;
				if (opt_value) { // value is passed explicically
					title = $child.firstChild.nodeValue
				}
				else {
					opt_value = $child.firstChild.nodeValue;
					title = this.Titles[$child.firstChild.nodeValue];
				}
				this.addOption($dst_field, opt_value, title, $child.attributes);
				break;
			case 'field_options':
				this.addOption($dst_field, '', $empty_title);
				// add new states
				this.ProcessXMLNode($child, $dst_field);

				/*if ($dst_field.options.length == 0 || $dst_field.options.length == 2) {
					$dst_field.value = $dst_field.options[$dst_field.options.length - 1].value;
				}*/
				break;
		}
	}
}

AjaxEventManager.prototype.removeOptions = function($object) {
	if (!$object) {
		$object = document.getElementById('filter_value');
	}
	if ($object.options.length > 0) {
		while ($object.options.length > 0) {
			$object.remove(0);
		}
	}
}

AjaxEventManager.prototype.addOption = function($object, $value, $title, attributes) {
	var $option = document.createElement('OPTION');
	$object.options.add($option, $object.options.length);
	$option.innerText = $title;
	$option.innerHTML = $title;
	$option.value = $value;
	if (attributes) {
		for (var i=0; i<attributes.length; i++) {
			if (attributes[i].nodeName == 'value') continue;
			$option.setAttribute(attributes[i].nodeName, attributes[i].nodeValue);
		}
	}
}

AjaxEventManager.prototype.refreshOptions = function ($filter_type, $empty_value_title) {
	this.removeOptions();

	var $url = this.URL.replace('#ID#', 0).replace('#EVENT#', 'OnGetFilterValues').replace('#FILTER_TYPE#', $filter_type);
	Request.makeRequest($url, this.BusyRequest, '', this.successCallback, this.errorCallback, ['filter_values', $filter_type, $empty_value_title], this);
}