/*
 *
 *
 *
*/
Ajax.Log = {
	debug: function(message){
		if(typeof window.jslog != 'undefined' && jsLog_enabled){
			jslog.debug(_format(message));
		}
	},
	
	error: function(message){
		if(typeof window.jslog != 'undefined' && jsLog_enabled){
			jslog.error(_format(message));
		}
	}
}

Ajax.Event = {
	buildSubject: function(controlName, eventName){
		if(!controlName || controlName==''){
			throw new Error('Ajax.Event.buildSubject. No control name.');
		}
		if(!eventName || eventName==""){
			throw new Error('Ajax.Event.buildSubject. No event.');
		}			

		return "ajax." + controlName + "." + eventName;
	},
	
	observe: function(controlName, eventName, scope, callback) {
		if(callback == null){
			throw new Error("Ajax.Event.observe. No callback function.");
		}
		
		var subj = Ajax.Event.buildSubject(controlName, eventName);
		var subs = PageBus.subscribe(subj, scope, callback);
		
		Ajax.Log.debug('Add observer for AJAX event: ' + subj);
	},

	fire: function(controlName, eventName, message) {
		var subject = this.buildSubject(controlName, eventName);
		Ajax.Log.debug('Fire event: ' + subject);
		PageBus.publish(subject, message);
	}
}

Ajax.Event.Message = Class.create();

Ajax.Event.Message.prototype = {
	jss: "org.pagebus.msg.Message",
	jssv: "1.0.0",
	head: {},
	body: null,
		
	initialize: function(body){
		this.body = body;
	}
}

Ajax.Control = Class.create();

Ajax.Control.prototype = {
	initialize: function(element, url, options){
		this.controlInitialize(element, url, options);
	},
	
	controlInitialize: function(element, url, options){
		Ajax.Log.debug('Create new Ajax.Control: ' + element);
		this.element = $(element);
		this.url = url;
		
		this.options = options || {};		
		this.options.paramName = this.options.paramName || this.element.name;
		this.options.defaultParams = this.options.parameters || null;
		this.options.onComplete = this.onComplete.bind(this);
	},
	
	getValue: function(){
		return $F(this.element);
	},
	
	setValue : function(value){
		Ajax.Log.debug(this.element.name +'. Set value :' + value);
		this.element.value = value;
	},
	
	getParameters: function(){
	    var entry = encodeURIComponent(this.options.paramName) + '=' + 
	      encodeURIComponent(this.getValue());

	    this.options.parameters = this.options.callback ?
	      this.options.callback(this.element, entry) : entry;

	    if(this.options.defaultParams) 
	      this.options.parameters += '&' + this.options.defaultParams;

		return this.options;
	},
	
	onAjaxEvent: function(subject, message, subscriberData){
		Ajax.Log.debug(this.element.name +'.OnAjaxEvent ' + subject);
	},
	
	onComplete: function(transport){
		Ajax.Log.debug(this.element.name +'. Ajax respond recieved.');
	}	
}


Ajax.Select = Class.create();

Object.extend(Ajax.Select.prototype, Ajax.Control.prototype);
Object.extend(Ajax.Select.prototype, {
	initialize: function(element, url, options){
		this.selectInitialize(element, url, options);
	},
	
	selectInitialize: function(element, url, options){
		this.controlInitialize(element, url, options);		
		
		this.options.insertion = this.options.insertion || Insertion.After;
		if(this.options.defaultParams){
			this.options.defaultParams += '&controllName=' + this.element.name;
		} else {
			this.options.defaultParams = 'controllName=' + this.element.name;		
		}
		
		this.onChangeListener = this.onChange.bind(this);
		
		Event.observe(this.element, 'change', this.onChangeListener);
	},
	
	onChange: function(event){
		Ajax.Event.fire(this.element.name, 'change');
		if(this.options.onChange){
			this.options.onChange.bind(this)();
		}
	},

	onAjaxEvent: function(subject, message, subscriberData){
		Ajax.Log.debug(this.element.name +'.OnAjaxEvent ' + subject);
		if(subject.match(/^ajax\..*\.change$/)){
			Ajax.Log.debug(this.element.name +'. Send Ajax request.');
			new Ajax.Updater({success: this.element.name, failure: null}, this.url, this.getParameters());
		}
		
		if(subject.match(/^ajax\..*\.select$/)){
			this.setValue(message.body[this.options.paramName]); 
		}	
	},

	onComplete: function(transport){
		Ajax.Log.debug(this.element.name +'. Ajax respond recieved.');
		if(200 == transport.status){
			var oldSelect = Element.remove(this.element);
			Event.stopObserving(oldSelect, 'change', this.onChangeListener);
			this.element = $(oldSelect.name);
			Event.observe(this.element, 'change', this.onChangeListener);
		}
	}	
});

Ajax.Group = Class.create();

Object.extend(Ajax.Group.prototype, {
	initialize: function(){
		Ajax.Log.debug('Create new Ajax.Group');
		args = $A(arguments);
		
		this.options = args.last();
		this.options.UNDEF_ID = this.options.UNDEF_ID || '-1';
				
		this.items = args.without(this.options);
		var itemInitializer = function(item){
			for(var property in item){
				if(property == 'control' && !item.control.options.callback){
					Ajax.Log.debug('Set "callback" method.');
					item.control.options.callback = this.getParameters.bind(this);
				} else {
					this.addEvent(item[property], property, item.control);
				}
			}
		}.bind(this);
			
		this.items.each(itemInitializer);
	},
	
	addEvent: function(source, event, target, method){
		var eventCreator = function(source){
			var callback = target[method ? method : 'onAjaxEvent'];
			if(source && target && callback){
				Ajax.Event.observe(source.element.id, event, target, callback);
			}		
		}.bind(this);
		
		if(source.each) {
			source.each(eventCreator);
		} else {
			eventCreator(source);
		}
	},
		
	getParameters: function (element, params){
		var paramBuilder = function(item){
			if(item.control.element != element){			
				params += '&' + encodeURIComponent(item.control.options.paramName) + '=' +
					this.encodeElementValue(item.control.element);
			}
		}.bind(this);
		
		this.items.each(paramBuilder);
		
		if(this.options.getParameters) {
			return this.options.getParameters(this, params);
		}
		
		return params;
	},
	
	encodeElementValue: function (element){
		return encodeURIComponent($(element).disabled ? '-1' : $F(element));
	}
});
