(function( $, undefined ) {

$.widget( "ui.tagselect", {
	options: {
		choices: {}, //assoziative array of choices
		splitter: ',', //splitter of choices in the source field 
		text_predefined: 'Predefined:',
		text_custom_input: 'Custom Input:',
		text_custom_add: 'add',
		custom_input: true
	},

	//id of source field
	id: null,
	
	//cached elems
	labelelem: null,
	choiceselem: null,
	mode: null,
	
	//these tags are currently selected
	choicesmade: null,
	
	// init
	_create: function() {
		var self = this;
		
		self.choicesmade = new Array();
		
		self.id = this.element.attr('id');
		
		self.mode = this.element.get(0).tagName;
		
		if(self.mode != 'INPUT' && self.mode != 'SELECT')
			return;
		
		//hide source field
		self.element.hide();
		
		//label is for displaying selected tags, choices is the popup window
		self.element.after('<div id="' + self.id + '-tagselect-labels" class="ui-tagselect-labels"></div>' +
				           '<div id="' + self.id + '-tagselect-choices" class="ui-tagselect-choices"></div>'
				           );
		
		//cache
		self.labelelem = $("#" + self.id + "-tagselect-labels");
		self.addbutton = $("#" + self.id + "-tagselect-add");
		self.choiceselem = $("#" + self.id + "-tagselect-choices");
		
		self.choiceselem.hide();
		
		//get the inital selected tags
		if(self.element.val())
		{
			if(self.mode == 'input')
				self.choicesmade = explode(self.options.splitter,self.element.val());
			else
				self.choicesmade = self.element.val();
		}
		
		//update the label, choices and the field
		self._update();
	},
	
	//cummulative update
	_update: function()
	{
		this._updateLabels();
		this._updateMenu();
		this._updateField();
	},	
	
	//write the selected tags back to the source field
	_updateField: function()
	{
		var self = this;
		
		if(self.mode == 'input')
			self.element.val(implode(self.options.splitter,self.choicesmade));
		else
			self.element.val(self.choicesmade);
	},
	
	//display the currently selected tags
	_updateLabels: function()
	{
		var self = this;		
		
		//clear the labels
		self.labelelem.html('');
		
		//add each selected tag to the display element
		$.each(self.choicesmade,function(index,tag){
			
			//Retrieve the name of the tag, if it exists in the choices option, otherwise use the tag itself as name
			var name = tag;
			if(self.options.choices[tag])
				name = self.options.choices[tag];
			
			self.labelelem.append('<div class="ui-tagselect-elem">' + name + '&nbsp;&nbsp;<a href="#" rel="' + tag + '" class="ui-tagselect-rm">&times;</a></div>');
		});	
		
		//handle click event to remove a tag
		self.labelelem.find('.ui-tagselect-rm').click(function(){			
			self._removeTag($(this).attr('rel'));
			return false;
		});
		
		//add the add button to the end
		self.labelelem.append('<div id="' + self.id + '-tagselect-add" class="ui-tagselect-elem"><a href="#" class="ui-tagselect-add">+</a></div>');
		
		//hande click event to toggle the popup
		self.labelelem.find('.ui-tagselect-add').click(function(){
			$('.ui-tagselect-choices').each(function(){
				if($(this) != self.choiceselem)
					$(this).hide();
			});
			self.choiceselem.toggle();
			return false;			
		});
		
	},
	_updateMenu: function()
	{
		var self = this;
		
		self.choiceselem.html('<a href="#" id="' + self.id + '-tagselect-close" class="ui-tagselect-close">&times;</a>');
		
		if(sizeof(self.options.choices) > 0)
		{
			//clean the popup
			self.choiceselem.append(self.options.text_predefined + '<br><ul></ul>');
			
			var menu = self.choiceselem.find('ul');
			
			//add the choices
			$.each(self.options.choices,function(tag,name) {				
				if(array_search(tag,self.choicesmade,false) === false)//only add unselected choices
					menu.append('<li><a href="#" rel="' + tag + '">' + name + ' (' + tag + ')' + '</a></li>');
			});
			
			//handle click event in the menu to add a tag
			menu.find('a').click(function(){
				self.choiceselem.hide();			
				self._addTag($(this).attr('rel'));
				return false;
			})
			
			//init the menu
			menu.menu();	
		}
		

		//handle click event to close popup
		$('#' + self.id + '-tagselect-close').click(function(){
			self.choiceselem.hide();
			return false;
		});		
		
		//add the custom field to the end of the popup
		if(self.options.custom_input){
			self.choiceselem.append(self.options.text_custom_input + '<br><input type="text"><button id="' + self.id + '-tagselect-custom-add">' + self.options.text_custom_add+ '</button>');
	
			//handle click event to add a custom tag
			$('#' + self.id + '-tagselect-custom-add').button();
			$('#' + self.id + '-tagselect-custom-add').click(function(){
				self._addCustomTag();
				return false;
			});
		}	
	},
	
	//add a tag to the selected ones
	_addTag: function(tag)
	{	
		var self = this;
		
		$.each(explode(self.options.splitter,tag),function(index,tag){
			if(array_search(tag,self.choicesmade) == false)			
				array_push(self.choicesmade, tag);
		});
		
		//do an update to show changes
		this._update();
		
	},
	
	//reads the custom tag and add it
	_addCustomTag: function()
	{
		if(!self.options.custom_input) return;
			
		var customtag = self.choiceselem.find('input').val();
		
		this.choiceselem.hide();
		
		if(!customtag) return;
		this._addTag(customtag);
	},
	
	//remove a tag from selected ones
	_removeTag: function(tag)
	{
		var self = this;
		
		//search for the tag 
		var index = array_search(tag,self.choicesmade);
		
		//exit if the tag was not found
		if(index === false) return;
		
		//remove the deleted tag from the selected ones
		var newchoices = new Array()
		$.each(self.choicesmade,function(myindex,elem){
			if(index != myindex)
				array_push(newchoices,elem);
		})
		self.choicesmade = newchoices;
		
		//do an update to show changes
		self._update();
	}
});

}( jQuery ));

