nClass('philox_elements_search', {
	id: null,
	elements: {
		container: null,
		help: null,
		icon: null,
		form: null,
		parameters: null,
		search: null,
		self: null
	},
	parameters: null,
	
	initialize: function(id, parameters) {
		this.id = id;
		this.parameters = parameters;
		
		this.elements = {}; // @bug nClass object is static
		this.elements.container = $(id + '_container');
		this.elements.help = $(id + '_help');
		this.elements.icon = $(id + '_icon');
		this.elements.form = $(id + '_form');
		this.elements.parameters = $(id + '_parameters');
		if (this.elements.parameters.innerHTML != '') this.elements.icon.onclick = this.onClickSearchIcon.bind(this);
		this.elements.search = $(id + '_search');
		this.elements.search.onblur = this.onBlurSearch.bind(this);
		this.elements.search.onfocus = this.onFocusSearch.bind(this);
		this.elements.search.onkeyup = this.onKeyUpSearch.bind(this);
		//XPS_addEvent(window, 'onload', function() { this.elements.search.focus(); this.elements.search.select(); }.bind(this));
		this.elements.self = $(id);
		
		this.hideParameters();
		this.hideHelp();
		XPS_setOnBlurCallback(this.elements.container, function() { this.hideParameters(); this.hideHelp(); }.bind(this));
	},
	
	hideHelp: function() {
		this.elements.help.hide();
	},
	
	hideParameters: function() {
		this.elements.parameters.hide();
	},
	
	onClickSearchIcon: function(e) {
		if (this.elements.parameters.getStyle('display') == 'none')
			this.showParameters();
		else
			this.hideParameters();
	},
	
	onBlurSearch: function(e) {
		this.hideHelp();
	},
	
	onFocusSearch: function(e) {
		this.showHelp();
		this.hideParameters();
	},
	
	onKeyUpSearch: function(e) {
		var e = XPS_getEventObject(e);
		
		switch ((e.keyCode) ? e.keyCode : e.which) {
			case 13:
				this.elements.self.value = this.elements.search.value;
				XPS_submit(this.elements.form, document.location.href);
				break;
			
			default:
				break;
		}
	},
	
	showHelp: function() {
		//this.elements.help.setStyle({ top: XPS_get_absolute_top(this.elements.container) + 20 + 'px' });
		
		this.elements.parameters.hide();
		this.elements.help.show();
	},
	
	showParameters: function() {
		//this.elements.parameters.setStyle({ top: XPS_get_absolute_top(this.elements.container) + 20 + 'px' });
		
		this.elements.help.hide();
		this.elements.parameters.show();
	}
});

nClass('philox_elements_multi_search', {
	id: null,
	idc: null,
	data: null,
	delay_timer: null,
	elements: { 
		container: null, 
		self: null,
		input: null,
		itemcontainer: null,
		matches: null
	},
	items: null,
	parameters: null,
	xhr: null,
	
	initialize: function(id, parameters) {
		this.id = id;
		this.idc = new Array();
		this.items = new Array();
		this.parameters = parameters;
		
		// container
		this.elements = {}; // @bug nClass object is static
		this.elements.container = $(id + '_container');
		this.elements.itemcontainer = $(id + '_itemcontainer');
		this.elements.itemanchor = $(id + '_itemanchor');
		
		// elements
		this.elements.self = $(id);
		this.elements.matches = $(id + '_matches');
		
		// initialize ajax
		this.xhr = new XHRClass();
		
		// bound onkeydown event to the input element
		this.elements.input = $(id + '_itemmatch');
		//this.elements.input.onblur = this.onBlurInputElement.bind(this);
		this.elements.input.onfocus = this.onFocusInputElement.bind(this);
		this.elements.input.onkeydown = this.onKeyDownInputElement.bind(this);
		
		XPS_setOnBlurCallback(this.elements.itemanchor, this.onBlurInputElement.bind(this));
		
		this.hideMatchesContainer();
		
		// add predefined items
		if (parameters['value'] != '') {
			this.addItems(parameters['value']);
			this.idc = parameters['value'].toString().split(',');
		}
	},
	
	addItems: function(idc) {
		var query = 
			this.parameters['xhr_url'] + '?' +
			'&philox_elements_xhr=1' +
			'&philox_elements_xhr_mode=id' +
			'&philox_id=' + this.id +
			'&philox_match=' + idc
		;
		this.xhr.send(query, true, this.addItemsCallback.bind(this));
	},
	
	addItemsCallback: function(reply) {
		this.data = null;
		if (reply) this.data = this.xhr.reply2MultiDimensionalArray(reply);
		
		if (this.data.length > 0) {
			// iterate through matches
			for (var index = 0; index < this.data.length; index++) {
				// add item to the selected items
				var item = 
					XPS_template_populate(
						this.parameters['template_item'],
						{ 
							id: this.id + '_item_' + this.data[index]['id'],
							description: XPS_template_populate(this.parameters['template_item_description'], this.data[index]),
							remove: XPS_template_populate(
								this.parameters['template_item_remove'], 
								{ onclick_remove: "javascript: window." + this.id + ".removeMatchItem(" + this.data[index]['id'] + ")" }
							)
						}
					);
				
				new Insertion.Before(this.elements.itemanchor, item);
			}
		}
	},
	
	addMatchItem: function(index) {
		if (!this.data) return;
		
		// id specified
		if (this.data[index]['id']) {
			// check if this id already has been added
			if (this.idc.indexOf(this.data[index]['id']) == -1) {
				// add id to idc
				this.idc[this.idc.length] = this.data[index]['id'];
				this.elements.self.value = this.idc.join(',');
				
				// add item to the items
				this.items[this.data[index]['id']] = this.data[index];
				
				// add item to the selected items
				var item = 
					XPS_template_populate(
						this.parameters['template_item'],
						{ 
							id: this.id + '_item_' + this.data[index]['id'],
							description: XPS_template_populate(this.parameters['template_item_description'], this.data[index]),
							remove: XPS_template_populate(
								this.parameters['template_item_remove'], 
								{ onclick_remove: "javascript: window." + this.id + ".removeMatchItem(" + this.data[index]['id'] + ")" }
							)
						}
					);
				
				new Insertion.Before(this.elements.itemanchor, item);
			}
			
			this.elements.input.value = '';
			this.refreshMatches();
			this.elements.input.focus();
			this.elements.input.select();
		}
		
		//this.hideMatchesContainer();
	},
	
	hideMatchesContainer: function() { 
		this.elements.input.value = '';
		this.elements.matches.hide();
	},
	
	onBlurInputElement: function(e) {
		this.hideMatchesContainer();
	},
	
	onFocusInputElement: function(e) {
		this.showMatchesContainer();
	},
	
	onKeyDownInputElement: function(e) {
		var e = XPS_getEventObject(e);
		
		switch((e.keyCode) ? e.keyCode : e.which) {
			case 9:
				this.onBlurInputElement();
				break;
			
			default:
				break;
		}
		
		// clear current timer if one already has been set
		if (this.delay_timer)
			window.clearTimeout(this.delay_timer);
		this.delay_timer = 
			window.setTimeout(
				'window.' + this.id + '.refreshMatches()',
				this.parameters['onkeyup_delay']
			);
	},
	
	refreshMatches: function() {
		var match = this.elements.input.value;
		
		if (match == '') {
			this.elements.matches.update('<div class="PhiloxMultiSearchElementMessage">' + this.parameters['lang_starttyping'] + '</div>');
		}
		else {
			var query = 
				this.parameters['xhr_url'] + '?' +
				'&philox_elements_xhr=1' +
				'&philox_id=' + this.id +
				'&philox_match=' + match
			;
			this.xhr.send(query, true, this.refreshMatchesCallback.bind(this));
		}
	},
	
	refreshMatchesCallback: function(reply) {
		this.data = null;
		if (reply) this.data = this.xhr.reply2MultiDimensionalArray(reply);
		
		if (this.data.length == 0) {
			// no matches found
			this.elements.matches.update('<div class="PhiloxMultiSearchElementMessage">' + this.parameters['lang_nomatches'] + '</div>');
		}
		else {
			// iterate through matches
			var html = '';
			var html_item = '';
			for (var i = 0; i < this.data.length; i++) {
				// onclick
				this.data[i]['onclick'] = "window." + this.id + ".addMatchItem(" + i + ")";
				
				html_item = 
					XPS_template_populate(
						this.parameters['template_match'],
						this.data[i]
					);
				
				html += html_item;
			}
			this.elements.matches.update(html);
		}
	},
	
	removeMatchItem: function(id) {
		// remove item
		this.items.splice(id, 1);
		this.idc.splice(this.idc.indexOf(id), 1);
		this.elements.self.value = this.idc.join(',');
		$(this.id + '_item_' + id).remove();
	},
	
	showMatchesContainer: function() {
		this.elements.matches.show();
		this.elements.matches.setStyle({ width: this.elements.container.offsetWidth + 'px' });
		this.refreshMatches();
	}
});
