
/*
 * TODO s
 * 
 */

(function($){
	$.fn.BionicDropdown = function(options){
		
		var __this__ = this;
		var callingClass = "bDropdown";
		var dropdownTriggerClass = "bDropdownTrigger";
		var dropdownClass = "bDropdownWrapper";
		var dropdownFirst = "bDropdownFirst";
		var dropdownSecond = "bDropdownSecond";
		var dropdownItem = "bDropdownItem";
		var dropdownLast = "bDropdownLast";
		
		var defaults = { 
				copyCallerId: true,
				copyCallerStyle: true,
				copyCallerClasses: true,
				onMouseover:null,
				onMouseout:null,
				postConstructor:null,
				onChange:null
		};
		
		this.options = $.extend(defaults, options);
		
		var open = false;
		
		var log = function(message){
			try{
				console.log(message);
			}catch(e){}
		}
		
		var backend = $(this);
		
		/*
		 * rebuild dropdown from backend
		 */
		__this__.update = function(){
			var selected = backend.find('option:selected').first();
			// make sure something is always selected, if nothing is select the first option
			if (selected.length==0){
				backend.find('option').first().attr('selected','selected');
			}
			selected = backend.find('option:selected').first();
			var caption = selected.text();
			var value = selected.attr('value');
			__this__.dropdown.children('ul').first().empty();
			__this__.dropdown.children('ul').first().append("<li value='"+value+"' class='"+dropdownFirst+"'>"+caption+"</li>");
			var lastLi = backend.find('option').not('option:selected').last();
			var secondLi = backend.find('option').not(selected).first();
			// generate remaining
			backend.find('option').not('option:selected').each(function(){
				var caption = $(this).text();
				var value = $(this).attr('value');
				if ( $(this).get(0) == secondLi.get(0) ){
					__this__.dropdown.children('ul').first().append("<li value='"+value+"' class='"+dropdownItem+" "+dropdownSecond+"' style='display:none'>"+caption+"</li>");
				}else if ( $(this).get(0) == lastLi.get(0) ){
					__this__.dropdown.children('ul').first().append("<li value='"+value+"' class='"+dropdownItem+" "+dropdownLast+"' style='display:none'>"+caption+"</li>");
				}else{
					__this__.dropdown.children('ul').first().append("<li value='"+value+"' class='"+dropdownItem+"' style='display:none'>"+caption+"</li>");
				}
				
			});
			
			bindEvents();
			hide();
			
			/* try postConstructor callback */
			try{
				__this__.options.postConstructor(__this__.trigger);
			}catch(e){}
		}
		
		var bindEvents = function(){
			__this__.dropdown.children('ul').children('li').not('.'+dropdownFirst).each(function(){
				$(this).unbind('mouseover').bind('mouseover', function(){
					try{
						__this__.options.onMouseoverItems(this);
					}catch(e){}
				});
			});
			
			__this__.dropdown.children('ul').children('li').not('.'+dropdownFirst).each(function(){
				$(this).unbind('mouseleave').bind('mouseleave', function(){
					try{
						__this__.options.onMouseoutItems(this);
					}catch(e){}
				});
			});
			
			__this__.trigger.unbind('click').bind('click',function(){
				if (open){
					hide();
				}else{
					show();
				}
				return false;
			});
			
			__this__.dropdown.children('ul').children('li').not('.'+dropdownFirst).each(function(){
				$(this).unbind('click').bind('click', function(e){
					e.stopPropagation();
					
					var selectedValue = $(this).attr('value');
					// 1) can the value be found?
					// 2) unselect whatever is currently selected
					// 3) select the current value
					// 4) update
					// FIXME why does value have be a number?
					var selectedBackend = backend.find('option[value="'+selectedValue+'"]');
					if (selectedBackend.length==0){return false;}
					hide();
					backend.find('option:selected').first().removeAttr("selected");
					selectedBackend.attr('selected','selected');
					__this__.update();
					
					/* try onChange callback */
					try{
						__this__.options.onChange();
					}catch(e){}
					return false;
				});
			});
			
			$(document).bind('click',function(){
				hide();
			})
			
			return;
		}
		
		var hide = function(){
			__this__.dropdown.children('ul').children('li').not(':first').css("display","none");
			open = false;
		}
		
		var show = function(){
			__this__.dropdown.children('ul').children('li').not(':first').css("display","block");
			open = true;
		}

		/*
		 * class constructor
		 */
		var constructor = function(){
			
			// verify
			if (!backend.is("select") || !backend.hasClass(callingClass)){
				log("BionicDropdown: aborting, calling element must have class= "+callingClass+" and be a SELECT");
				return;
			}
			
			// inject trigger markup
			__this__.trigger = $('<div></div>');
			if (__this__.options.copyCallerClasses==true){
				__this__.trigger.attr("class", backend.attr("class"));
				__this__.trigger.removeClass(callingClass);
			}
			if (__this__.options.copyCallerId==true){
				__this__.trigger.attr("id", backend.attr("id"));
			}
			if (__this__.options.copyCallerStyle==true){
				__this__.trigger.attr("style", backend.attr("style"));
			}
			
			__this__.trigger.addClass(dropdownTriggerClass);
			__this__.trigger.insertAfter(backend);
			__this__.trigger.css("cursor","pointer");
			__this__.trigger.width(backend.width());
			__this__.trigger.height(backend.height());
			
			// disable text selection on the trigger
			__this__.trigger.css("-webkit-user-select","none");
			__this__.trigger.css("-moz-user-select","none");
			if ($.browser.msie){
				__this__.trigger.get(0).onselectstart = function() { return false; };
			}
			
			// hide backend
			backend.css("display","none");
			
			// inject dropdown markup
			__this__.dropdown = $('<div></div>');
			__this__.dropdown.addClass(dropdownClass);
			__this__.dropdown.append('<ul></ul>');
					
			__this__.dropdown.appendTo(__this__.trigger);
			
			__this__.update();
			

		}();
		
	};
})(jQuery);

