/** 
 * 	AjaxGroups (c)2007
 *  A. Karasev 
 * 	Used: jslog.js, pagebus.js, prototype.js
 */

if(typeof window.AjaxUtils == 'undefined'){
	
	function _getMessage(obj){
		return {
				jss: "org.pagebus.msg.Message",
				jssv: "1.0.0",
				head: {},
				body: obj				
			};
	}

	var AjaxEventProxy = {
		listeners: [],
		
		initialize:function(){
			
		},
		
		registerListener:function(controlName, eventName, scope, callback){
			if(controlName == null || controlName==""){
				throw new Error("AjaxEventProxy. No control name.");
			}
			if(eventName == null || eventName==""){
				throw new Error("AjaxEventProxy. No event.");
			}			
			if(callback == null){
				throw new Error("AjaxEventProxy. No callback function.");
			}
			var subs = PageBus.subscribe(this.subj(controlName,eventName), scope, callback);
			this.listeners.push([controlName, eventName, scope, callback, subs]);
		},
		
		addAjaxEvent:function(controlName, eventName){
			var proxy = this;
			Event.observe(controlName, eventName, function(event){
				proxy.onAjaxEvent(controlName, eventName, event);
			}.bindAsEventListener(), false);
		},
		
		removeAjaxEvent:function(controlName){
			
		},
		
		onAjaxEvent:function(controlName, eventName, event){
			PageBus.publish(this.subj(controlName,eventName), _getMessage(event));	
		},
		
		subj:function(controlName, eventName){
			return controlName + "." + eventName;
		}
	}
		
	AjaxEventProxy.initialize();
	
	var AjaxUtils = {
		groups: $H({}),
			
		initialize: function(){
			if(typeof window.jslog != 'undefined' && jsLog_enabled){	
				jslog.debug(_format("Initialize AjaxUtils"));
			}
			
			Ajax.Responders.register({
				onComplete: function(responder, request, transport, json){
					if(typeof window.jslog != 'undefined' && jsLog_enabled){
						jslog.debug(_format("Ajax response received"));
					}
					
					var params = extractAJAXObject(request);
					
					if(params == null){
						return;
					}
					
					var groupName = params['group'];
					if(groupName != null){
						if(typeof window.jslog != 'undefined' && jsLog_enabled){
							jslog.debug(_format("Update event published for group: " + groupName));
						}
						PageBus.publish(groupName+".ajax.onComplete", this.getMessage(params));	
					} else {
						if(typeof window.jslog != 'undefined' && jsLog_enabled){
							jslog.warn(_format("No group name in response."));
						}
						PageBus.publish("noGroup.ajax.onComplete", this.getMessage(params));
					}
				},
				
				getMessage:function(params){
					return _getMessage(params);
				}
			});
			
			Event.observe(window, "unload", AjaxUtils.finalize.bindAsEventListener(AjaxUtils), false);			
		},
		
		finalize:function(){
			if(typeof window.jslog != 'undefined' && jsLog_enabled){
				jslog.debug(_format("Finalize AjaxUtils"));
			}
		},
				
		registerGroup:function(group){
			if(group.name == null){
				if(typeof window.jslog != 'undefined' && jsLog_enabled){
					jslog.warn(_format("AjaxUtils: Group without name."));
				}
				return;
			}
			
			if(typeof window.jslog != 'undefined' && jsLog_enabled){
				jslog.debug(_format("AjaxUtils: register group: " + group.name));
			}
			
			this.groups[group.name] = group;
			group.subscription = PageBus.subscribe(group.name+".onChange", this, this.sendRequest, group);
		},
		
		unregisterGroup:function(group){
			if(typeof window.jslog != 'undefined' && jsLog_enabled){
				jslog.debug(_format("AjaxUtils: unregister group: " + group.name));
			}
			this.groups.remove(group.name);
			PageBus.unsubscribe(group.subscription);
		},
		
		registerControl:function(groupName, control){
			if(typeof window.jslog != 'undefined' && jsLog_enabled){
				jslog.debug(_format("AjaxUtils: register control in group " + groupName));
			}
			var group = this.groups[groupName];
			if(group != null){
				group.addControl(control);
			} else {
				if(typeof window.jslog != 'undefined' && jsLog_enabled){
					jslog.warn(_format("AjaxUtils: No group without name: " + groupName));
				}
			}
		},
		
		unregisterControl:function(groupName, control){
			if(typeof window.jslog != 'undefined' && jsLog_enabled){
				jslog.debug(_format("AjaxUtils: unregister control from group " + groupName));
			}
			var group = this.groups[groupName];
			if(group != null){
				group.removeControl(control);
			}		
		},
		
		sendRequest:function(subj, message, group){
			if(typeof window.jslog != 'undefined' && jsLog_enabled){
				jslog.debug(_format("AjaxUtils: send request"));
			}
			ajaxInvoke(
				group.url,
				{ method: 'get', 
				  parameters: group.getQueryString(message.body)
				} 
			);
		}
	}
	
	AjaxUtils.initialize();
	
	AjaxGroup = Class.create();
	
	AjaxGroup.prototype = {
		controls: null,
		name: "",
		url: "",
		method: "",
		params: "",
		subscription: null,
		prefix: "",
		
		initialize: function(name, prefix, url, method, params){
			if(typeof window.jslog != 'undefined' && jsLog_enabled){
				jslog.debug(_format("Create AjaxGroup: " + name));
			}
			this.name = name;	
			this.url = url;
			this.method = method;
			this.params = params;
			this.prefix = prefix;
			this.controls = [];
		},
		
		addControl:function(ajaxControl){
			this.controls[this.controls.length] = ajaxControl;
			ajaxControl.group = this;
			ajaxControl.subscription[0] = PageBus.subscribe(this.name + ".ajax.onComplete", ajaxControl, ajaxControl.onAjaxResponse, null);
			ajaxControl.subscription[1] = PageBus.subscribe("noGroup.ajax.onComplete", ajaxControl, ajaxControl.onAjaxResponse, null);
		},
		
		removeControl:function(ajaxControl){
			this.controls = this.controls.without(ajaxControl);
			if(ajaxControl.subscription.length > 0){
				PageBus.unsubscribe(ajaxControl.subscription[0]);
				PageBus.unsubscribe(ajaxControl.subscription[1]);
			}
		},
		
		getQueryString:function(ajaxControl){
			var queryString = "action=" + this.method + "&group=" + this.name;
			
			if(ajaxControl != null){
				queryString += "&updateField=" + ajaxControl.updateField;
			}else{
				queryString += "&updateField=init";
			}
			
			if (this.prefix != null && this.prefix != "") {
				queryString += "&prefix=" + this.prefix;
			}
			
			if (this.params != null && this.params != "") {
				queryString += "&" + this.params;
			}
			
			if(ajaxControl == null || !ajaxControl.useOnlyThisControl){
				this.controls.each(function(control){
					queryString += "&" + control.getQueryString();
				});
			} else {
				queryString += "&" + ajaxControl.getQueryString();
			}
			
			if(typeof window.jslog != 'undefined' && jsLog_enabled){
				jslog.debug(_format("AjaxGroup. Query string: " + queryString));
			}
			
			return queryString;
		},
		
		sendInitRequest:function(){
			PageBus.publish(this.name + ".onChange", _getMessage(null), this);
		}
	}
	
	AjaxControl = Class.create();
	
	AjaxControl.prototype = {
		control: null,
		group: null,
		options: null,
		subscription: null,
		updateField: null,
		useOnlyThisControl: false,
		
		initialize:function(control, options){
			if(typeof window.jslog != 'undefined' && jsLog_enabled){
				jslog.debug(_format("Create AjaxControl: " + control));
			}
			this.control = control;
			this.updateField = control;
			this.options = options;
			this.subscription = [];			
			this.initControl();
		},
		
		sendMessage:function(){
			PageBus.publish(this.getSubject(), this.getMessage());
		},
		
		getSubject:function(){
			if(this.group != null){
				return this.group.name + ".onChange";
			} else {
				throw new Error("AjaxControl. No group found.");
			}
		},
		
		getMessage:function(){
			return _getMessage(this);
		},
		
		getQueryString:function(){
			throw new Error("AjaxControl. Method does not exist.");
		},
		
		onAjaxResponse:function(subj, message, data){
			throw new Error("AjaxControl. Method does not exist.");
		},
		
		initControl:function(){
			throw new Error("AjaxControl. Method does not exist.");
		}
	}	
}