//searchhelper.js
//works in conjunction with the cakephp Search Helper
//to create a dynamic search query field
//BTW.  Totally rocks.

//first, a utility function that should be included in prototype.js
//needle is a string/int of the value of the desired option
//haystack is the select element (str id or element node itself) that needs to be changed
Form.Element.setSelect = function(needle, haystack) {
	var selectMe = $A($(haystack).options).find(function(opt) {
		if (opt.value == '') {
			opt.value = opt.innerHTML; //work around IE mishandling 'empty' value attributes
		}
		return (opt.value == needle);
	}.bind(needle));
	selectMe.selected = true;
};


var SearchHelper = new Class.create();

SearchHelper.prototype = {

	initialize:function(myId) {
		this.search = null;
		this.id = myId;
		this.observers = $A([]);
		this.rows = 0;
		$(this.id).appendChild(
			Builder.node('input', {id: this.id + '-submit', 'type':'submit', 'value':'Search'})
		);
		Form.disable($(this.id));
		this.textTerms = $A(['matches', 'contains', 'does not contain', 'starts with', 'ends with', 'does not start with', 'does not end with']);
		if (!($('table-' + this.id))) {
			$(this.id).appendChild(
				Builder.node('table', {id: 'table-' + this.id, 'class':'searchTable'}, [
					Builder.node('tbody', {id: 'table-body-' + this.id})
				])
			);
		}
		$(this.id).appendChild(Builder.node('input', {id: this.id + '-clear', 'type':'hidden', name: 'data[' + this.id + '][clear]', 'value': 1}));
	},
	
	setParams:function(o) {
		this.search = o;
	},
	
	setTerms:function(o) {
		//setup the table with search terms from the prior search
		if (o.length != 0) {
			o = $H(o);
			o.each(function(term) {
			  this.addFromTerm(term);
			}.bind(this));
		}
	},
	
	add:function(r) {
		if (typeof(r) == 'undefined') {
			r = false;
		}
		//add a row to my table
		if (this.rows == 0) {
			Form.enable($(this.id));
		}
		if ($(this.id + '-clear')) { $(this.id + '-clear').parentNode.removeChild($(this.id + '-clear')); }
		var t = $($('table-body-' + this.id));
		rid = 0;
		do {
			rid++;
		} while ($(this.id + '-tr-' + rid))
		t.appendChild(Builder.node('tr', {id: this.id + '-tr-' + rid}, [
			Builder.node('td', [Builder.node('select', {id: this.id + '-noun-' + rid, name: 'data[' + this.id + '][' + rid + '][noun]'})]),
			Builder.node('td', [Builder.node('select', {id: this.id + '-verb-' + rid, name: 'data[' + this.id + '][' + rid + '][verb]'})]),
			Builder.node('td', {id: this.id + '-container-' + rid}),
			Builder.node('td', [
				Builder.node('a', {'href':"javascript:sH.add()"}, '+'),
				Builder.node('a', {'href':"javascript:sH.remove(" + rid + ")"}, '-')
			])
		]));
		var sNouns = $H(this.search).keys();
		sNouns.each(function(k){
			$(this.id + '-noun-' + rid).appendChild(Builder.node('option', k));
		}.bind(this));
		$(this.id + '-noun-' + rid).options[0].selected = true;
		//alert(rid);
		this.observers[rid] = {verb: null, directObj: null};
		this.changeVerbs(rid);
		this.observers[rid].verb = new Form.Element.EventObserver(
		    $($(this.id + '-noun-' + rid)), function(e) {
		    	var reg = /-noun-([0-9]+)/;
		    	var r = reg.exec(e.id);
		    	this.changeVerbs(r[1]);
		    }.bind(this)
		);
		this.rows++;
		if (r) {
			return rid;
		}
	},
	
	addFromTerm:function(o) {
		//add a row to my table from the saved term 'o'
		var rid = this.add(true);
		Form.Element.setSelect(o.value.noun, this.id + '-noun-' + rid);
		this.changeVerbs(rid);
		this.observers[rid].verb = new Form.Element.EventObserver(
		  $(this.id + '-noun-' + rid), function(e) {
		  	var reg = /-noun-([0-9]+)/;
		  	var r = reg.exec(e.id);
		  	this.changeVerbs(r[1]);
		  }.bind(this)
		);
		Form.Element.setSelect(o.value.verb, this.id + '-verb-' + rid);
		this.changeDirectObject(rid);
		this.observers[rid].directObj = new Form.Element.EventObserver(
		  $($(this.id + '-verb-' + rid)), function(e) {
		  	var reg = /-verb-([0-9]+)/;
		  	var r = reg.exec(e.id);
		  	this.changeDirectObject(r[1]);
		  }.bind(this)
		);
		
		var type = o.value.verb;
		if (this.textTerms.find(function(t){ return (t == type)})) { type = 'text'; }
		if (type == 'text') {
		  $(this.id + '-field-' + rid + '-0').value = o.value.field;
		  $(this.id + '-do-' + rid).value = o.value['do'];
		} else {
			Form.Element.setSelect(o.value['do'], this.id + '-do-' + rid);
		}
	},
	
	remove: function(rid) {
		//remove row 'rid' to the table
		//clear observers
		this.observers[rid] = {verb: null, directObj: null};
		$(this.id + '-tr-' + rid).parentNode.removeChild($(this.id + '-tr-' + rid));
		this.rows--;
		if (this.rows == 0) {
			$(this.id).appendChild(Builder.node('input', {'type':'hidden', 'id': this.id + '-clear', 'name': 'data[' + this.id + '][clear]'}));
		}
	},
	
	clear: function() {
		this.rows = 0;
		$(this.id + '-table').innerHTML = '';
		$(this.id).appendChild(Builder.node('input', {'type':'hidden', 'id': this.id + '-clear', 'name': 'data[' + this.id + '][clear]'}));
	},
	
	changeVerbs: function(rid) {
		var sVerbs = $H(this.search[$F(this.id + '-noun-' + rid)]).keys();
		var v = $($(this.id + '-verb-' + rid));
		v.innerHTML = '';
		v.show();
		sVerbs.each(function(k){
			if (k == 'text') {
				this.textTerms.each( function(nk) {
					v.appendChild(Builder.node('option', nk));
				}.bind(this));
			} else {
				v.appendChild(Builder.node('option', k));
			}
			if (k == 'value') {
				v.hide();
			}
		}.bind(this));
		v.options[0].selected = true;
		this.changeDirectObject(rid);
		this.observers[rid].directObj = new Form.Element.EventObserver(
			v, function(e) {
				var reg = /-verb-([0-9]+)/;
				var r = reg.exec(e.id);
				this.changeDirectObject(r[1]);
			}.bind(this)
		);
	},
	
	changeDirectObject: function(rid) {
		var type = $F(this.id + '-verb-' + rid);
		if (this.textTerms.find(function(t){ return (t == type)})) { type = 'text'; }
		var container = $(this.id + '-container-' + rid);
		container.innerHTML = '';
		if (type == 'text') {
			container.appendChild(Builder.node('input',{type:'hidden', 'id': this.id + '-field-' + rid + '-0', 'name': 'data[' + this.id + '][' + rid + '][field][0]', 'value': this.search[$F(this.id + '-noun-' + rid)].text}));
			container.appendChild(Builder.node('input',{ 'id': this.id + '-do-' + rid, 'name': 'data[' + this.id + '][' + rid + '][do]'}));
		} else if (type == 'value') {
			container.appendChild(Builder.node('select', { 'id': this.id + '-do-' + rid, 'name': 'data[' + this.id + '][' + rid + '][do]'}));
			var sel = $(this.id + '-do-' + rid);
			var ks = $H(this.search[$F(this.id + '-noun-' + rid)].value).keys();
			var vs = $H(this.search[$F(this.id + '-noun-' + rid)].value).values();
			ks.each(function(k,i) {
				sel.appendChild(Builder.node('option',{'value': vs[i]}, k));
			}.bind(this));
			sel.options[0].selected = true;
		} else {
			container.appendChild(Builder.node('select', { 'id': this.id + '-do-' + rid, 'name': 'data[' + this.id + '][' + rid + '][do]'}));
			var sel = $(this.id + '-do-' + rid);
			var fs = $A(this.search[$F(this.id + '-noun-' + rid)][type][0]);
			fs.each(function(f,i) {
				container.appendChild(Builder.node('input',{type:'hidden', 'id': this.id + '-field-' + rid + '-' + i, 'name': 'data[' + this.id + '][' + rid + '][field][' + i + ']', 'value': f}));
			}.bind(this));
			var ks = $A(this.search[$F(this.id + '-noun-' + rid)][type][1]);
			ks.each(function(k) {
				sel.appendChild(Builder.node('option',{'value': k.value}, [k.name]));
			}.bind(this));
			sel.options[0].selected = true;
		}
	}

};