(function($){

	jQuery.fn.extend({ 
		disableSelection : function() { 
			return this.each(function() { 
				this.onselectstart = function() { return false; }; 
				this.unselectable = "on"; 
				jQuery(this).css('user-select', 'none'); 
				jQuery(this).css('-o-user-select', 'none'); 
				jQuery(this).css('-moz-user-select', 'none'); 
				jQuery(this).css('-khtml-user-select', 'none'); 
				jQuery(this).css('-webkit-user-select', 'none'); 
			}); 
		} 
	});

	$.widget("rb.selectlist", {
		options: {
			debugMode: true
		},

		_create: function(){
			var SL = this;

			this.element.wrap($('<div/>', {
				"class": "ui-widget ui-selectlist ui-selectlist-container"
			}));

			this.element.change(function(ev) {
			});

			this._container = this.element.parent('.ui-selectlist');

			this._select = this.element.clone()
				.attr('data-represents', (this.element.attr('id') || this.element.attr('name').replace(/[\[|\]]/ig, "").replace(/[^a-z-_]+/gi, "-")))
				.removeAttr('multiple')
				.removeAttr('size')
				.removeAttr('id')
				.removeAttr('name')
				.addClass('ui-selectlist-representative');

			if (!(this.options.firstOptionIsPlaceholder || this.element.data('first-option-is-placeholder') === true)) {
				this.options["placeholder"] = this.options["placeholder"] ||
					this.element.attr('title') ||
					this.element.attr('placeholder') ||
					this.element.data('placeholder') ||
					"Select an item to add";


				this._select.prepend($("<option/>", {
					"class": "ui-selectlist-placeholder-option",
					"text": this.options.placeholder
				}));
			} else {
				this._select.find('option:first').addClass('ui-selectlist-placeholder-option');
			}

			this._select.bind('change', function(ev) {
				SL.select($(this).val());
				SL.selectPlaceholder();
			});

			this.selectPlaceholder();

			this._container.append(this._select);

			this.element.hide();

			this._list = $('<ol/>', {
				"class": "ui-selectlist-list"
			}).appendTo(this._container);

			this.refreshList();

			// remember this instance
			$.rb.selectlist.instances.push(this.element);
		},

		_init: function(){

		},

		select: function(value) {
			var selectOpt = this.getSelectOptionByValue(value, this.element);
			selectOpt.attr('selected', 'selected').trigger('change',  [{
				'option': selectOpt,
				'value': selectOpt.val(),
				'item': selectOpt,
				'type': 'add'
			}]);
			this.refreshList();
		},

		selectPlaceholder: function() {
			this._select.find('option:selected').attr('selected', false);
			this._select.find('option.ui-selectlist-placeholder-option').attr('selected', true);
		},

		refreshList: function() {
			var sel = this.element.find('option:selected')
			  , SL = this
			  ;
			sel.each(function() {
				SL.addListItem(this);
			});
		},

		addListItem: function(optEl) {
			var SL = this, existing, removeLink, li, selectOpt;
			optEl = $(optEl);
			existing = this._list.find('li').filter(function() {
				return $(this).data('selectlist-value') == optEl.val();
			});

			if (existing.length > 0) return;

			if (optEl.is('.ui-selectlist-placeholder-option')) return;

			removeLink = $('<span/>', {
				"class": "ui-icon ui-icon-circle-close ui-selectlist-item-remove-link",
				"click": function() {
					var val = $(this).parent('li').data('selectlist-value');
					SL.removeListItem(val);
				}
			});

			li = $('<li/>', {
					"class": "ui-state-default ui-selectlist-list-item",
					"text": optEl.text()
				}).append(removeLink);

			li.data('selectlist-option', optEl);
			li.data('selectlist-value', optEl.val());

			li.disableSelection();

			selectOpt = this.getSelectOptionByValue(optEl.val(), this._select);

			selectOpt.attr('disabled', true).addClass('ui-state-disabled');
			li.appendTo(this._list);
		},


		removeListItem: function(val) {
			var selectOpt, optEl,
				li = this._list.find('li').filter(function() {
				return $(this).data('selectlist-value') === val;
			});
			li.remove();
			optEl = this.getSelectOptionByValue(val, this._select);
			optEl.attr('disabled', false).removeClass('ui-state-disabled');

			selectOpt = this.getSelectOptionByValue(val, this.element);
			selectOpt.removeAttr('selected').trigger('change',  [{
				'option': selectOpt,
				'value': selectOpt.val(),
				'item': selectOpt,
				'type': 'remove'
			}]);
		},


		// ----------------------------------------------------------------------



		getSelectOptionByValue: function(value, selectEl) {
			var opts, opt;
			opts = $(selectEl).find('option').filter(function() {
				return $(this).val() === value;
			});
			if (opts.length < 1) {

				opt = $('<option/>', {
					"value": value,
					"text": value
				});
				opt.appendTo($(selectEl));
				return opt;
			}
			return opts.eq(0);
		},


		destroy: function(){
			// remove this instance from $.rb.selectlist.instances
			var element = this.element,
				position = $.inArray(element, $.rb.selectlist.instances);

			// if this instance was found, splice it off
			if(position > -1){
				$.rb.selectlist.instances.splice(position, 1);
			}

			// call the original destroy method since we overwrote it
			$.Widget.prototype.destroy.call( this );
		},

		_getOtherInstances: function(){
			var element = this.element;

			return $.grep($.rb.selectlist.instances, function(el){
				return el !== element;
			});
		}

/*
		_setOption: function(key, value){
			this.options[key] = value;

			switch(key){
				case "something":
					// perform some additional logic if just setting the new
					// value in this.options is not enough.
					break;
			}
		}*/

	});

	$.extend($.rb.selectlist, {
		instances: []
	});

}(jQuery));
