/* edits:
	options.* -> settings.*
	if(settings.source)
		source = settings.source;
	else source = $("select",this);
*/
(function($){

	var defaults = {
		source:			null,
	  	onChange:		null,
		initialValue:	'',
		size:			5
	};

	var methods = {
		init:function(options){		
			return $(this).each(function(){
				var settings = {};
				$.extend(settings, defaults, options);
				
				settings.source ? source = settings.source : source = $('select', $(this));
				
				var data = $(this).data('iwsDropdown2');
					labelwrapper = $('<div>', {className:'iws-dropdown-labelwrapper'});
					leftcap = $('<div>', {className:'iws-dropdown-leftcap'});
					label = $('<div>', { className:'iws-dropdown-label', temp:source.attr('id') }),
					arrow = $('<div>', { className:'iws-dropdown-arrow' }),
					list_wrapper = $('<div>', { className:'iws-dropdown-list-wrapper' });
					list_container = $('<div>', { className:'iws-dropdown-list-container' }).appendTo(list_wrapper);
				
				if(!data){
					//add the label, arrow and the list
					labelwrapper.append(leftcap,label);
					$(this).append(labelwrapper, arrow, list_wrapper);
					
					//initialize data
					$(this).data('iwsDropdown2', {
						settings: settings,
						onChange: settings.onChange,
						initialValue: settings.initialValue,
						source: source,
						label: label,
						arrow: arrow,
						list_wrapper: list_wrapper,
						list_container: list_container,
						isOpen:false
					});
					
					//events
					label.bind('click.iwsDropdown2', methods.toggleList);
					arrow.bind('click.iwsDropdown2', methods.toggleList);
					source.bind('change.iwsDropdown2', methods.sourceChange)
					.bind('keyup.iwsDropdown2', methods.sourceKeyUp)
					.bind('focus.iwsDropdown2', methods.sourceFocus)
					.bind('blur.iwsDropdown2', methods.sourceBlur);
					
					//generate list items
					list_container.empty();
					var listItem = null;
					var count = 0;
					
					function addItem(i) {
						if($(i).text() != ''){
							var labelText = $(i).text();
							
							if($(i).is('optgroup')){
								labelText = $(i).attr('label');
							}
							
							listItem = $('<div>', { className:'iws-dropdown-item', value:$(i).val(), text:labelText }).appendTo(list_container);

							if($(i).is('optgroup')){
								listItem.addClass('iws-dropdown-group');
								listItem.attr('value', 'null');
							} else {
								//option is disabled
								if($(i).attr('disabled') == true){
									listItem.addClass('iws-dropdown-item-disabled');
								} else {
									listItem.bind('click.iwsDropdown2', methods.select);
								}
							}
							
							//option is selected, trigger it
							if($(i).is(':selected')){
								label.text($(i).text());
								listItem.addClass('iws-dropdown-item-selected');
							}
							
							count++;
						}
					}
					
					source.children('option').each(function(){
						addItem($(this));
					})
					
					source.children('optgroup').each(function() {
						addItem($(this));
						$(this).children('option').each(function() {
							addItem($(this));
						});
					});
					
					//show the source, its initially display none for no fouc. needs to be displayed to recieve focus
					source.show();
					
					//no default option, and initial value is not blank
					if(source.find("option[selected='true']").length == 0 && settings.initialValue != ''){
						label.text(settings.initialValue);
					}
					
					//truncate size setting if actual list contains fewer items
					var actualSize = count < settings.size ? count : settings.size;
					
					//set proper height based on size value in settings
					if(count > 0){
						var padding = parseInt(listItem.css('padding-top')) + parseInt(listItem.css('padding-bottom'));
						list_wrapper.height(actualSize * (listItem.outerHeight() + padding));
						list_wrapper.find('.iws-dropdown-item:last-child').css('border-bottom', 0);
					}
					
					if(count > actualSize){
						list_wrapper.iwsSlider({ onDrag:methods.onDrag });
					};
				}
			});
		},

		select:function(){
			var list_item = $(this)
				dropdown = list_item.closest('.iws-dropdown'),
				source = dropdown.data('iwsDropdown2').source
				option = source.find("option[value='" + list_item.attr('value') + "']");
			
			dropdown.iwsDropdown2('close');
			option.attr('selected', true);
			source.trigger('focus.iwsDropdown2').trigger('change.iwsDropdown2');
			$(window).unbind('mousedown.iwsDropdown2');
		},
		
		sourceChange:function(e){
			var source = $(this),
				option = source.find('option:selected');
				dropdown = source.closest('.iws-dropdown'),
				label = dropdown.data('iwsDropdown2').label,
				list_container = dropdown.data('iwsDropdown2').list_container,
				onChange = dropdown.data('iwsDropdown2').onChange,
				initialValue = dropdown.data('iwsDropdown2').initialValue
			
			list_container.find('.iws-dropdown-item').each(function(i){
				$(this).removeClass('iws-dropdown-item-selected');
			});
			
			if(option.val() == '' && option.text() == ''){
				label.text(initialValue);
			} else {
				list_container.find('.iws-dropdown-item[value="' + option.val() + '"]').each(function(){
					if($(this).text() == option.text()){
						$(this).addClass('iws-dropdown-item-selected');
						label.text($(this).text());
					}
				});
			}
			
			if(onChange && option){
				onChange.apply(this, [source, option.attr('value'), option.text()]);
			}
		},
		
		sourceKeyUp:function(e){
			methods.sourceChange.apply(this, arguments);
		},
		
		sourceFocus:function(e){
			$(this).closest('.iws-dropdown').data('iwsDropdown2').label.toggleClass('iws-dropdown-focus', true);
		},
		
		sourceBlur:function(e){
			$(this).closest('.iws-dropdown').data('iwsDropdown2').label.toggleClass('iws-dropdown-focus', false);
		},
		
		toggleList:function(){
			var dropdown = $(this).closest('.iws-dropdown'),
				isOpen = dropdown.data('iwsDropdown2').isOpen
				
			dropdown.iwsDropdown2(isOpen ? 'close' : 'open');
		},
		
		open:function(){
			var dropdown = $(this);
			
			$('.iws-dropdown').iwsDropdown2('close');
			
			dropdown.children('.iws-dropdown-list-wrapper').css('z-index', 9999999999).show();
			dropdown.data('iwsDropdown2').isOpen = true;
			
			$(window).bind('mousedown.iwsDropdown2', function(e){
				if($(e.target).closest('.iws-dropdown').length == 0) {
					$(window).unbind('mousedown.iwsDropdown2');
					dropdown.iwsDropdown2('close');
				}
			});
		},
		
		close:function(){
			var dropdown = $(this);
			
			dropdown.children('.iws-dropdown-list-wrapper').css('z-index', 1).hide();
			dropdown.data('iwsDropdown2').isOpen = false;
		},
		
		onDrag:function(src, n){
			var dropdown = src.closest('.iws-dropdown')
				list_container = dropdown.data('iwsDropdown2').list_container;
				list_wrapper = dropdown.data('iwsDropdown2').list_wrapper;
				
			var ht = (list_container.height() - list_wrapper.height()) * n;
			list_container.css("margin-top", -ht);
		},
		
		setValue:function(val){
			return this.each(function(){
				var src = $(this);
					dropdown = src.closest('.iws-dropdown');
					list_container = dropdown.data('iwsDropdown2').list_container;
				
				list_container.find(".iws-dropdown-item[value='" + val + "']").trigger('click.iwsDropdown2');
			})
		},
		
		setLabel:function(){
			return this.each(function(){
				var list_container = $(this).data('iwsDropdown2').list_container;
				
				list_container.find('.iws-dropdown-item').each(function(){
					if($(this).text() == val){
						$(this).trigger('click.iwsDropdown2');
					}
				});
			})
		},
		
		destroy:function(){
			return this.each(function(){
				var dropdown = $(this),
					data = dropdown.data('iwsDropdown2');
				
				if(data){
					data.label.remove();
					data.arrow.remove();
					data.list_wrapper.remove();
				}
				
				dropdown.data('iwsDropdown2', null);
			});
		}
  };
  
  $.fn.iwsDropdown2 = function(method){
		if (methods[method]){
		  	return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
		} else if (typeof method === 'object' || !method) {
		  	return methods.init.apply(this, arguments);
		} else {
		  	$.error('Method ' +  method + ' does not exist on jQuery.iwsDropdown2');
		}    
  };
  
})(jQuery);
