(function($) {
	$.fn.asmSelect = function(customOptions) {
		var options = {
			listType: 'ol',
			sortable: false,
			highlight: false,
			animate: false,
			addItemTarget: 'bottom',
			hideWhenAdded: false,
			debugMode: false,

			highlightAddedLabel: 'Добавлено: ',
			highlightRemovedLabel: 'Удалено: ',

			containerClass: 'asmContainer',
			selectClass: 'asmSelect',
			optionDisabledClass: 'asmOptionDisabled',
			listClass: 'asmList',
			listSortableClass: 'asmListSortable',
			listItemClass: 'asmListItem',
			removeClass: 'asmListItemBlock',
			highlightClass: 'asmHighlight'
			};

		$.extend(options, customOptions);
		return this.each(function(index) {
			var $original = $(this);
			var $container;
			var $select;
			var $ol;
			var buildingSelect = false;
			var ieClick = false;

			function init() {
				$select = $("<select></select>")
					.addClass(options.selectClass)
					.attr('id', options.selectClass + options.element);

				$selectRemoved = $("<select></select>");

				$ol = $("<" + options.listType + "></" + options.listType + ">")
					.addClass(options.listClass)
					.attr('id', options.listClass + options.element);

				$container = $("<div></div>")
					.addClass(options.containerClass)
					.attr('id', options.containerClass + options.element);

				buildSelect();

				$select.change(selectChangeEvent)
					.click(selectClickEvent);

				$original.change(originalChangeEvent)
					.wrap($container).before($select).before($ol);

				if(options.sortable) makeSortable();

				if($.browser.msie) $ol.css('display', 'inline-block');
			}

			function makeSortable() {
				$ol.sortable({
					items: 'li.' + options.listItemClass,
					handle: '.' + options.removeClass,
					axis: 'y',
					update: function() {
						$(this).children("li").each(function(n) {
							if($(this).is(".ui-sortable-helper")) return;
							$option = $('#' + $(this).attr('rel'));
							$original.append($option);
						});
					}
				}).addClass(options.listSortableClass);
			}

			function selectChangeEvent() {
				if($.browser.msie && $.browser.version < 7 && !ieClick) return;
				var id = $(this).children("option:selected").slice(0,1).attr('rel');
				addListItem(id);
				ieClick = false;
			}

			function selectClickEvent() {
				ieClick = true;
			}

			function originalChangeEvent() {
				$select.empty();
				$ol.empty();
				buildSelect();
			}

			function buildSelect() {
				buildingSelect = true;
				$select.prepend("<option>" + $original.attr('title') + "</option>");
				$original.children("option").each(function(n) {
					var $t = $(this);
					var id;
					if(!$t.attr('id')) $t.attr('id', 'asm' + options.element + 'Option' + n);
					id = $t.attr('id');
					if($t.is(":selected")) {
						addListItem(id);
						addSelectOption(id, true);
					} else {
						addSelectOption(id);
					}
				});
				if(!options.debugMode) $original.hide();
				selectFirstItem();
				buildingSelect = false;
			}

			function addSelectOption(optionId, disabled) {
				if(disabled == undefined) var disabled = false;
				var $O = $('#' + optionId);

				var $option = $("<option>" + $O.text() + "</option>")
					.val($O.val())
					.attr('rel', optionId);
				if(disabled) disableSelectOption($option);
				$select.append($option);
			}

			function selectFirstItem() {
				$select.children(":eq(0)").attr("selected", true);
			}

			function disableSelectOption($option) {
				$option.addClass(options.optionDisabledClass)
					.attr("selected", false)
					.attr("disabled", true);
				if(options.hideWhenAdded) $option.hide();
				if($.browser.msie) $select.hide().show();
			}

			function enableSelectOption($option) {
				$option.removeClass(options.optionDisabledClass)
					.attr("disabled", false);

				if(options.hideWhenAdded) $option.show();
				if($.browser.msie) $select.hide().show();
			}

			function addListItem(optionId) {
				var $O = $('#' + optionId);
				if(!$O) return;

				var $textLink = $("<b></b>")
					.prepend(clearItem($O.html()));

				var $removeLink = $("<a></a>")
					.attr("href", "#")
					.addClass(options.removeClass)
					.append($textLink)
					.click(function() {
						dropListItem($(this).parent('li').attr('rel'));
						return false;
					});

				var $item = $("<li></li>")
					.attr('rel', optionId)
					.addClass(options.listItemClass)
					.append($removeLink)
					.hide();

				if(!buildingSelect) {
					if($O.is(":selected")) return;
					$O.attr('selected', true);
				}

				if(options.addItemTarget == 'top' && !buildingSelect) {
					$ol.prepend($item);
					if(options.sortable) $original.prepend($O);
				} else {
					$ol.append($item);
					if(options.sortable) $original.append($O);
				}

				addListItemShow($item);

				disableSelectOption($("[rel=" + optionId + "]", $select));

				if(!buildingSelect) {
					setHighlight($item, options.highlightAddedLabel);
					selectFirstItem();
					if(options.sortable) $ol.sortable("refresh");
				}
			}

			function clearItem(string) {
				string = string.toString();
				string = string.replace(/\¦\-\&nbsp\;/g, '');
				string = string.replace(/\¦\&nbsp\;\&nbsp\;/g, '');
				return string;
			}

			function addListItemShow($item) {
				if(options.animate && !buildingSelect) {
					$item.animate({
						opacity: "show",
						height: "show"
					}, 100, "swing", function() {
						$item.animate({
							height: "+=2px"
						}, 50, "swing", function() {
							$item.animate({
								height: "-=2px"
							}, 25, "swing");
						});
					});
				} else {
					$item.show();
				}
			}

			function dropListItem(optionId, highlightItem) {
				if(highlightItem == undefined) {
				var highlightItem = true;
				}
				var $O = $('#' + optionId);

				$O.attr('selected', false);
				$item = $ol.children("li[rel=" + optionId + "]");
				dropListItemHide($item);
				enableSelectOption($("[rel=" + optionId + "]", options.removeWhenAdded ? $selectRemoved : $select));

				if(highlightItem) {
					setHighlight($item, options.highlightRemovedLabel);
				}


			}

			function dropListItemHide($item) {
				if(options.animate && !buildingSelect) {
					$prevItem = $item.prev("li");
					$item.animate({
						opacity: "hide",
						height: "hide"
					}, 100, "linear", function() {
						$prevItem.animatez({
							height: "-=2px"
						}, 50, "swing", function() {
							$prevItem.animate({
								height: "+=2px"
							}, 100, "swing");
						});
						$item.remove();
					});

				} else {
					$item.remove();
				}
			}

			function setHighlight($item, label) {
				if(!options.highlight) return;
				$select.next("#" + options.highlightClass + options.element).remove();
				var $highlight = $("<span></span>")
					.hide()
					.addClass(options.highlightClass)
					.attr('id', options.highlightClass + options.element)
					.html(label + $item.children("." + options.removeClass).slice(0,1).text());

				$select.after($highlight);
				$highlight.fadeIn("fast", function() {
					setTimeout(function() { $highlight.fadeOut("slow"); }, 50);
				});
			}

			init();
		});
	};

})(jQuery);

