// v.2 2009-06-01-14-51, ignores preselect zeroes

function SelectFeeder() {
	var watched = {};
	var cache = {};
	var stable = true;
	
	var hook = function(object, event, callback, phase) {
		object.addEventListener(event, callback, phase);
	};
	if (typeof window.addEventListener == 'undefined') {
		hook = function(object, event, callback, phase) {
			object.attachEvent('on' + event, callback );
		};
	};
	
	function XHR () {
		if (window.XMLHttpRequest)     // Object of the current windows
			return xhr = new XMLHttpRequest();     // Firefox, Safari, ...
		else if (window.ActiveXObject)   // ActiveX version
			return new ActiveXObject("Microsoft.XMLHTTP");  // Internet Explorer
		return null;
	}
	
	// Call callback with JSON corresponding to selected values
	function broccoli(callback, preselect) {
		var xhr = XHR();
		var key = '';
		xhr.onreadystatechange = function() {
			if (xhr.readyState == 4) {
				//alert(xhr.responseText);
				//console.log(xhr.responseText);
				//alert(xhr);
				var json = eval('(' + xhr.responseText + ')');
				//alert(json);
				cache[key] = json
				callback(json);
			
			};
		};
		if (!preselect)
			for (vok in watched) {
				voc = watched[vok];
				if (voc.element.value) {
					if (key) key += '_';
					key += String(voc.element.value);
				}				
			}
		else
			key = preselect.replace(/,/g, '_'); 
			
		if (typeof cache[key] == 'undefined') {
			var req = key.replace(/_/g, ',');
			xhr.open('GET', '/feed/broccoli.json?' + req, true);
			xhr.send(null);
		}
		else {
			callback(cache[key]);
		}
	}
	
	// Empty select box, insert 'any' item
	function select_prune() {
		while (this.element.length)
			this.element.remove(0);
		this.append({tid: 0, name: this.any});
	}
	
	// Add option to select
	function select_append(option) {
		var opt = document.createElement('option');
		opt.text = option.name;
		opt.value = option.tid; 
		try {
			this.element.add(opt, null);
		} catch (e) {
			this.element.add(opt);
		}
	}
	
	// BTW, it's not select method
	function select_preselect(preselect) {
		var _ps = preselect.split(',');
		var voc, opt;
		var i, j;
		var ps = [];
		for (i=0; i < _ps.length; i++)
			if (_ps[i] != '0')
				ps.push(_ps[i]);
		for (vok in watched) {
			voc = watched[vok].element;
			try {
				for (i=0; i<voc.childNodes.length; i++) {
					opt = voc.childNodes[i];
					if ((opt.nodeType == 1) && (opt.nodeName == 'OPTION'))				
						for (j=0; j<ps.length; j++)
							if (ps[j] == opt.value) {
								voc.value = ps[j];
								throw new Exception();
							}
				}
			} catch (e) {}
		}
	}
	
	// REFRESHED
	function refresh(preselect) {
		stable = false;
		broccoli(function (json) {
			var i;
			var visible;
			var select;
			var v;
			for (voc in json) {
				if (typeof(watched[voc]) == 'undefined')
					continue
				visible = json[voc];
				select = watched[voc];
				v = select.element.value || 0;
				select.prune();
				for (i=0; i<visible.length; i++)
					select.append(visible[i]);
				select.element.value = v;
			}
			if (preselect)
				select_preselect(preselect);
			for (vok in watched)
				if (watched[vok].onupdate)
					watched[vok].onupdate();
			stable = true;
		}, preselect);
	}
	
	/*function caller(x) {
		if (typeof x != undefined && x.tagName)
			return x;
		return window.event.srcElement
	}*/

	function watch(id, element, any, onupdate) {
		watched[id] = {element: element, any: any, prune: select_prune, append: select_append, onupdate: onupdate};
		hook(element, 'change', function () { /* avoid event object */ refresh(); }, false);
	}
	
	return {
		refresh: refresh,
		watch: watch,
		stable: function () {return stable;}
	};
}
