/*
 * PHP Road client-side request class
 */

var Phpr_Request = new Class({
	AjaxRequest: null,

	setOptions: function(options)
	{
		this.options = {
			uri: null,
			handler: null,
			handlerParams: null,
			componentClass: null,
			componentId: null,
			componentHandler: null,
			remote: false,
			postBody: null,
			onComplete: Class.empty,
			evalScripts: false,
			onFailure: Class.empty,
			postBodyOnly: false,
			errorBlockId: 'Message'
		};
		Object.extend(this.options, options || {});
	},

	initialize: function(options)
	{
		this.form = document.forms.length ? document.forms[0] : null;
		this.setOptions(options);
		this.request();
	},

	request: function()
	{
		if (!this.options.remote)
		{
			if (!this.form) return;
			if (this.options.uri) this.form.action = this.options.uri;

			var event = this.generateHandlerName();
			if (event != null)
				this.createHidden(event, 1);

			if (this.options.handlerParams) this.createHidden('phpr_handler_params', this.options.handlerParams);
			if (this.options.componentClass) this.createHidden('phpr_component_class', this.options.componentClass);
			if (this.options.componentId) this.createHidden('phpr_component_id', this.options.componentId);

			this.form.submit();
			return;
		} else 
		{
			var action = this.options.uri ? this.options.uri : (this.form ? this.form.action : null);

			var pairs = null;

			if (!this.options.postBodyOnly)
				pairs = $(this.form).toQueryString();

			pairs = this.addPostValue( pairs, "phpr_remote_event", 1 );

			var event = this.generateHandlerName();
			if (event != null)
				pairs = this.addPostValue(pairs, event, 1);

			pairs += '&' + this.options.postBody;

			if (this.options.handlerParams) pairs = this.addPostValue( pairs, "phpr_handler_params", this.options.handlerParams );
			if (this.options.componentClass) pairs = this.addPostValue( pairs, "phpr_component_class", this.options.componentClass );
			if (this.options.componentId) pairs = this.addPostValue( pairs, "phpr_component_id", this.options.componentId );

			var ajaxOptions = {};
			Object.extend(ajaxOptions, this.options)

			ajaxOptions.postBody = pairs;

			this.AjaxRequest = new Ajax(action, ajaxOptions);
			this.AjaxRequest.request();
		}
	},

	createHidden: function(name, value)
	{
		this.form.appendChild(function()
		{
			this.type = "hidden";
			this.name = name;
			this.value = value;
			return this;
		}.bind(document.createElement('input'))());
	},

	generateHandlerName: function()
	{
		if (this.options.handler != null && this.options.handler.indexOf('{') == -1)
			this.options.handler = 'cmev' + this.options.componentId + '{' + this.options.handler + '}';

		var handlers = [];
		if (this.options.handler) handlers.push(this.options.handler);
		if (this.options.componentHandler) handlers.push(this.options.componentHandler);

		if (handlers.length)
			return handlers.join('|');

		return null;
	},

	addPostValue: function(post, name, value)
	{
		return post + "&" + name + "=" + encodeURIComponent(value);
	}
});

Element.extend({
	focusFirst: function() 
	{
		for (var el=0; el < this.elements.length; el++)
		{
			var TagName = this.elements[el].tagName;

			if ( (((TagName == 'INPUT' && this.elements[el].type != 'hidden')) || TagName == 'SELECT' || TagName == 'BUTTON' || TagName == 'TEXTAREA') && !this.elements[el].disabled && $(this.elements[el]).isVisible() )
			{
				this.elements[el].focus();
				break;
			}
		}

		return true;
	},

	focusField: function(field)
	{
		var fieldObj = $type(field) == 'string' ? $(field) : field;

		if (fieldObj && !fieldObj.disabled && fieldObj.isVisible())
			fieldObj.focus();
	},

	hide: function()
	{
		this.addClass('Hidden');
	},

	show: function()
	{
		this.removeClass('Hidden');
	},

	isVisible: function()
	{
		var CurrentParent = this;
		while (CurrentParent != null && CurrentParent != document)
		{
			if ($(CurrentParent).hasClass('Hidden'))
				return false;

			CurrentParent = CurrentParent.parentNode;
		}

		return true;
	}
});

Element.extend({
	toObject: function(){
		var obj = {};
		$$('input', 'select', 'textarea').each(function(el){
			var name = $(el).name;
			var value = el.getValue();
			var tag = el.getTag();

			if ( !(tag=='input' && el.type=='button') )
				if ((value !== false) && name) obj[name] = value;
		}); 
		return obj;
	}
});

var Ajax = Ajax.extend({
	multi: 'multi',
	responseText: null,

	onComplete: function(){
		if (this.options.update) 
		{
			if (this.options.update != this.multi)
				$(this.options.update).setHTML(this.response.text);
			else
				this.multiupdate(this.response.text);
		}
		if (this.options.evalResponse) eval(this.response.text);
		if (this.options.evalScripts) this.evalScripts.delay(30, this);
		this.fireEvent('onComplete', [this.response.text, this.response.xml], 20);
	},

	onSuccess: function(){
		this.fireEvent('onBeforeComplete', this);
		this.response = {
			'text': this.responseText,
			'xml': this.transport.responseXML
		};
		this.fireEvent('onSuccess', [this.response.text, this.response.xml]);
		this.fireEvent('onComplete', [this.response.text, this.response.xml], 20);
		this.callChain();
	},

	onFailure: function(){
		this.fireEvent('onBeforeComplete', this);
		this.fireEvent('onFailure', this);
		this.fireEvent('onAfterError', this);
		this.fireEvent('onComplete', [this.response.text, this.response.xml], 20);
	},

	onStateChange: function(){
		this.fireEvent('onStateChange', this.transport);
		if (this.transport.readyState != 4) return;
		var status = 0;
		try {status = this.transport.status} catch (e){}
		if (this.isSuccess()) this.onSuccess();
		else 
		{
			this.response = {
				'text': this.responseText,
				'xml': this.transport.responseXML
			};
			this.evalScripts.delay(30, this);
			this.onFailure();
		}
		this.transport.onreadystatechange = Class.empty;
	},

	multiupdate: function(responseText)
	{
		var pattern = />>[^<>]*<</g; 
		var Patches = responseText.match(pattern);
		if (!Patches) return;
		for ( var i=0; i < Patches.length; i++ )
		{
			var index = responseText.indexOf(Patches[i]) + Patches[i].length;
			var updateHtml = (i < Patches.length-1) ? responseText.slice( index, responseText.indexOf(Patches[i+1]) ) :
				responseText.slice(index);
			var updateId = Patches[i].slice(2, Patches[i].length-2);
			$(updateId).setHTML(updateHtml); 
		}
	},

	isSuccess: function(){
		var TestStr = "@AJAX-ERROR@";
		var ResponseText = this.transport.responseText;

		if ( ResponseText.test(TestStr) )
		{
			this.responseText = ResponseText.replace(TestStr, '');
			return false;
		}

		this.responseText = ResponseText;
		return true;
	}
});

String.extend({
	removeScripts: function(){
		return this.replace(/<script[^>]*?>[\S\s]*?<\/script>/g, '');
	}
});

Tips.implement({
	setOptions: function(options)
	{
		this.options = {
			transitionStart: Fx.Transitions.sineInOut,
			transitionEnd: Fx.Transitions.sineInOut,
			maxTitleChars: 30,
			fxDuration: 150,
			maxOpacity: 1,
			timeOut: 100,
			className: 'tooltip',
			align: 'left'
		}
		Object.extend(this.options, options || {});
	},

	locate: function(evt){
		var doc = document.documentElement;
		var top = evt.clientY + doc.scrollTop + 15 + 'px';

		var left = this.options.align == 'left' ?  evt.clientX + doc.scrollLeft - 30 + 'px' : evt.clientX + doc.scrollLeft - parseInt(this.toolTip.offsetWidth) + 30 + 'px';

		this.toolTip.setStyles({'top': top, 'left': left});
	},

	disappear: function(){
		this.fx.options.transition = this.options.transitionEnd;
		this.fx.custom(this.fx.now, 0);
	}
});


var CookieWriter = {
	write: function(key, value, duration, path, domain, secure){
		var date = new Date();
		date.setTime(date.getTime()+duration*1000);
		path = path || '/';

		var cookieStr = key+"="+value+"; expires="+date.toGMTString()+"; path="+path+"; security="+secure;
		if (domain)
			cookieStr += "; domain="+$domain;

		document.cookie = cookieStr;
	},

	clear: function(key){
		this.write(key, '', -1);
	}
};