/*
 ************* API ************** 
 * data: should be formatted like this : data = [ { videoid : "id1", name : "name1" }, { videoid : "id2" , name : "name2" } ];
 * 
 * TODO:
 * 1. expose a public 'data injection' function so we can update the data (see tablesorter example)
 * 
 */

;(function($){
	
	$.fn.customDropdown = function( data, options ){
		
		//support multiple instances
		if ( this.length > 1 ){
			this.each(function(){ $(this).customDropdown(options); });
			return this;
		}
		
		var settings = $.extend({
			hoverCSS: 	"selector-hover",
			listCSS: 	"dropdown-list",
			onSelect: 	function(){},
			onOpen: 	function(){},
			delay: 		500,
			listSize: 	15,
			dataFields: [ "name", "videoid" ],
			prev: 		"last page",
			next: 		"next page"
		}, options);
		
		//globals
		var selector = $(this);
		var currentId = $(this).find("span").attr("id");
		var list;
		var currentPage = 1;
		var lastPage;
		
		//initialize
		buildList();
		prepareEvents();
		
		/* ------------------------ functions ------------------------ */
		// create and append the list
		
		function buildList(){
			list = $("<ul></ul>");
			list.addClass( settings.listCSS );
			
			if ( data.length > settings.listSize ){
				addPagination();
			}
			
			//use the smaller of the two...
			var size = ( data.length < settings.listSize ) ? data.length : settings.listSize;
			generateListElements( 0, size );

			//position list
			selector.parent().css( "position", "relative" );
			positionList();
			
			//hide and append
			list.hide();
			$("body").append(list);
		};
		
		function generateListElements( startingIndex, endingIndex ){
			for ( var i = endingIndex - 1; i >= startingIndex; i-- ){ 
				var li = $("<li></li>");
				var text = data[i][settings.dataFields[0]];
				var id = data[i][settings.dataFields[1]];
				li.append( text );
				li.attr("id", id );
				li.click( function(){ 
					itemClicked( $(this).attr("id"), $(this).html() );
				});
				list.prepend(li);
			}
			maintainPaginationState();
		};
		
		function addPagination(){
			lastPage = Math.ceil(data.length / settings.listSize);
			var pagination = $("<li class=\"pagination\"></li>");
			var prev = $("<a class=\"left\">" + settings.prev + "</a>");
			var next = $("<a class=\"right\">" + settings.next + "</a>");
			var clear = $("<div class='clear'></div>");
			prev.click( function(event){
				event.stopPropagation();
				goToPage("prev");
			});
			next.click( function(event){
				event.stopPropagation();
				goToPage("next");
			});
			pagination.append(prev);
			pagination.append(next);
			pagination.append(clear);
			list.append(pagination);
		};
		
		function goToPage( page ){
			if ( page == "next" ){
				if ( currentPage == lastPage ){
					return;
				}
				currentPage++;
			} else if ( page == "prev" ){
				if ( currentPage == 1 ){
					return;
				}
				currentPage--;
			} else {
				page = Number(page);
				if ( page != lastPage && page > 0 ){
					currentPage = page;
				} else {
					return;
				}
			}
			
			refreshData();
		};
		
		function refreshData(){
			var startingIndex = (currentPage - 1) * settings.listSize;
			var endingIndex = startingIndex + settings.listSize;
			if ( endingIndex > data.length ){
				endingIndex = data.length;
			}
			clearList();
			generateListElements( startingIndex, endingIndex);
		};
		
		function maintainPaginationState(){
			if ( currentPage == lastPage ){
				list.find(".pagination > .right").hide();
			} else {
				list.find(".pagination > .right").show();
			}
			
			if ( currentPage == 1 ){
				list.find(".pagination > .left").hide();
			} else {
				list.find(".pagination > .left").show();
			}
		}
		
		function clearList(){
			list.children("li:not(.pagination)").remove();
		}
		
		function itemClicked( id, name ){
			toggleList( false );
			swapSelected( id, name );
			settings.onSelect( id, name );
		}
		
		function swapSelected( id, name ){
			selector.find("span").attr("id", id );
			selector.find("span").html( name );
		}
		
		function positionList(){
			list.css( { left : selector.offset().left, top: selector.offset().top + selector.outerHeight() - 1, width: selector.outerWidth() - 2 } );
		}
		
		// prepare and initialize events for the selector
		function prepareEvents(){
			prepareSelectorHover();
			prepareSelectorClick();
			prepareBodyClick();
		}
		
		function prepareSelectorHover(){
			selector.hover( 
				function(){
					selector.addClass( settings.hoverCSS );
				},
				function(){
					if ( list.is(":visible") ){
						return;
					} else {
						selector.removeClass( settings.hoverCSS );
					}
				}
			);
		}
		
		function prepareSelectorClick(){
			selector.click( function(){
				toggleList();
				return false;
			});
		}
		
		function prepareBodyClick(){
			$("body").click( function(event){    
                if ( list.is(":visible") ){
                    toggleList( false );
                }
            });
		}
		
		// toggle the list
		function toggleList( state ){
			if (data.length == 0){
				return;
			}
			
			if ( state == true ){
				list.slideDown( settings.delay );
				positionList();
				settings.onOpen();
			} else if ( state == false ){
				list.slideUp( settings.delay );
				selector.removeClass( settings.hoverCSS );
			} else {
				if ( list.is(":visible") ){
					toggleList( false );
				} else {
					toggleList( true);
				}
			}
		}
	}
	
})(jQuery);