/*!
 * (c) 2011 SysIQ, Inc. All rights reserved.
 *
 * This product is protected by United States laws,
 * international copyright treaties and all other applicable
 * national or international laws.
 *
 * This software may not, in whole or in part, be copied,
 * photocopied, translated, modified, or reduced to any
 * electronic medium or machine readable form
 * without the prior written consent of SysIQ, Inc.
 *
 * Filename: styled select
 * Author:   Bogdan Ivko
 */
(function($) {

/****************************************************************************************************************************
@@
@@		zIndex - must have a value less than previsious
@@		additionalWidth - Add if needed to make '.scrollSelect' wider
@@		structure - must contain [listPlace] in place you want to see element
@@
****************************************************************************************************************************/

	var defaults = {
		containerClass: 'styledSelect',
		rewritingClass: 'styledSelect',
		liBeforeScroll: 7,
		zIndex: 100,
		structure: '<ul></ul>',
		additionalWidth: 0,
		showScrollBar: false
	}

	$.fn.styledSelect = function(opt) {
		var options =  $.extend({}, defaults, opt);
		var optionArray = {
			click: {},
			liCount: {},
			liWidth: {},
			resize: {},
			scrollTop: {},
			ulTop: {},
			liHeight: {}
		}
		$(this).each(function(e){
			var select = $(this);
			var liSelected = select.find("option:selected").text();
			var liSelectedIndex = select.find("option:selected").index();
			optionArray.click[e] = 0;
			optionArray.liCount[e] = 0;
			optionArray.liWidth[e] = 0;
			optionArray.resize[e] = 0;
			optionArray.scrollTop[e] = 0;
			optionArray.ulTop[e] = 0;
			optionArray.liHeight[e] = 0;
			
			/*Clear structuer in case doubel conection*/
			if(select.parent().hasClass(options.rewritingClass)){
				select.parent().find('.shownSelect').remove();
				select.parent().find('.scrollSelect').remove();
				select.parent().addClass(options.containerClass).removeClass(options.rewritingClass);
			}else{
				select.wrap('<div class="'+options.containerClass+'" />');
			}
			
			/*adding elements*/
			var container = select.parent();
			options.structure = options.structure.replace('[listPlace]',defaults.structure);
			container.append('<span class="shownSelect"><span>'+liSelected+'</span></span>');
			container.append('<div class="scrollSelect">'+options.structure+'<div class="scrollBar"><span>&nbsp;</span></div></div>');
			select.find('option').each(function(){
				container.find('ul').append('<li>'+$(this).text()+'</li>')
				optionArray.liCount[e] ++;
			});
			container.find('li:eq('+liSelectedIndex+')').addClass('liSelected');
			if(select.attr('disabled')) container.addClass('selectDisabled');
			
			/*CSS fix*/
			if(container.parent().css("position")=='static'){
				container.parent().css("position","relative");
			};
			select.css({
				position: 'absolute',
				top: '0',
				left: '0',
				visibility: 'hidden'
			});
			container.css('z-index',options.zIndex);
			options.zIndex = options.zIndex - 1;
			
			/*Click to open list and update selected*/
			container.find("li").click(function() {
				select.find('option').each(function(){
					if($(this).attr('selected')) $(this).attr('selected','');
				});
				select.find('option:eq('+$(this).prevAll().length+')').attr('selected','selected');
				
				select.trigger("change");
			});	
			select.change(function(){
				container.find('.shownSelect span').text(select.find("option:selected").text());
				container.find('li').removeClass('liSelected');
				container.find('li:eq('+select.find("option:selected").prevAll().length+')').addClass('liSelected');
			});
			
			/*List hover*/
			container.find('li').mouseenter(function(){
				container.find('li').removeClass('liSelected');
				$(this).addClass('liSelected');
			});
			
			/*Select hover*/
			container.find('.shownSelect').mouseenter(function(){
				$(this).addClass('shownSelectHover');
			});
			container.find('.shownSelect').mouseleave(function(){
				$(this).removeClass('shownSelectHover');
			});
			
			/*Open select*/
			container.find('.shownSelect').click(function(){
				if(!select.attr('disabled')){
					if(!$(this).hasClass('shownSelectOpened')){
						optionArray.click[e] = 2;
						$(this).addClass('shownSelectOpened');
						$(this).next().css({
							height: 0,
							display: 'block'
						});
						
						
						
						/*Scroll list*/

						if(optionArray.liCount[e] > options.liBeforeScroll && options.showScrollBar===true){
							
							
							container.find('.scrollBar').css({
								display: 'block',
								height: ( container.find('ul').height() * (options.liBeforeScroll/optionArray.liCount[e]) - parseInt(container.find('.scrollBar').css('padding-top').split('px')[0]) - parseInt(container.find('.scrollBar').css('padding-bottom').split('px')[0]))+'px'
							});
							container.find('.scrollSelect').css({
								overflow: 'hidden'
								//height: ( container.find('ul').innerHeight() * (options.liBeforeScroll/optionArray.liCount[e]) )+'px'
							});
							
							var scrollHeight = container.find('ul').innerHeight() * (options.liBeforeScroll/optionArray.liCount[e]);
							container.find('.scrollSelect').animate({
								height: scrollHeight+'px'
							},500,function(){
								/*Resizing .scrollBar span acording to count of elements*/
								container.find('.scrollBar span').css('height',(container.find('.scrollBar').height() * container.find('.scrollSelect').innerHeight()) / container.find('ul').innerHeight());
								optionArray.scrollTop[e] = container.find('.scrollBar').height() - container.find('.scrollBar span').innerHeight() - parseInt(container.find('.scrollBar span').css('border-top-width').split('px')[0]) - parseInt(container.find('.scrollBar span').css('border-bottom-width').split('px')[0]);
								optionArray.ulTop[e] = container.find('ul').innerHeight() - container.find('.scrollSelect').innerHeight();
								optionArray.liHeight[e] = container.find('li:first').innerHeight() + parseInt(container.find('li:first').css('border-top-width').split('px')[0])  + parseInt(container.find('li:first').css('border-bottom-width').split('px')[0]);
							});
							
							/*Moving list with click on scrollbar*/
							$('.scrollBar').click(function(mouse){
								var scrollBarElem = $(this);
								optionArray.click[e] = 2;	
								if( mouse.pageY <= ( scrollBarElem.offset().top + scrollBarElem.find('span').innerHeight()/2 ) ){
									scrollBarElem.find('span').animate({top: '0'},150)
									container.find('ul').animate({top: '0'},150)
								}else if( mouse.pageY >= ( scrollBarElem.offset().top + (scrollBarElem.height() - scrollBarElem.find('span').innerHeight()/2) ) ){
									scrollBarElem.find('span').animate({top: optionArray.scrollTop[e]},150)
									container.find('ul').animate({top: -optionArray.ulTop[e]},150)
								}else{
									scrollBarElem.find('span').animate({top: mouse.pageY - scrollBarElem.offset().top - scrollBarElem.find('span').innerHeight()/2},150)
									container.find('ul').animate({top: - (optionArray.ulTop[e] * (mouse.pageY - scrollBarElem.offset().top - scrollBarElem.find('span').innerHeight()/2)) / optionArray.scrollTop[e]},150)
								}
							});
						}else{
							container.find('.scrollSelect').animate({
								height: container.find('ul').innerHeight()+'px'
							},300);
						}
						
						/*Setting width to conteiner with long LI*/
						container.find('li').each(function(){
							if(optionArray.liWidth[e] < $(this).width()) optionArray.liWidth[e] = $(this).innerWidth();
						});
						if(optionArray.liWidth[e] >= container.find('.scrollSelect').width() && optionArray.resize[e]==0){
							if (optionArray.liCount[e] <= options.liBeforeScroll){
								container.find('.scrollSelect').width(optionArray.liWidth[e] +options.additionalWidth);
							}else{
								container.find('.scrollSelect').width(optionArray.liWidth[e] + container.find('.scrollBar').innerWidth()+options.additionalWidth);
							}
						}else if(optionArray.resize[e]==0){
							optionArray.resize[e] ++;
							container.find('ul').css('width',container.find('.scrollSelect').width());
						}
						
						/*Drag select*/
						container.find('.scrollBar span').draggable({
							axis: "y",
							containment: "parent",
							scroll: false,
							drag: function(event, ui) {
								container.find('ul').css('top', - (optionArray.ulTop[e] * parseInt($(this).css('top').split('px')[0])) / optionArray.scrollTop[e] );
							}
						});
					}
				}
			});
			
			/*Moving select sith mouse wheel*/
			container.find('ul').bind('mousewheel',function(event, delta, deltaX, deltaY) {
				if (delta > 0){
					/*to top*/
					if(parseInt(container.find('ul').css('top').split('px')[0]) < 0){
						if(parseInt(container.find('ul').css('top').split('px')[0]) + container.find('li:first').innerHeight() < 0){
							container.find('ul').css('top',parseInt(container.find('ul').css('top').split('px')[0]) + optionArray.liHeight[e]);
							container.find('.scrollBar span').css('top',-( (parseInt(container.find('ul').css('top').split('px')[0]) * optionArray.scrollTop[e]) / optionArray.ulTop[e] ));
						}else{
							container.find('ul').css('top',0);
							container.find('.scrollBar span').css('top',0);							
						}
					}
				}else if (delta < 0){
					/*to bottom*/
					var maxTop = container.find('.scrollSelect').innerHeight() - container.find('ul').innerHeight();
					if(parseInt(container.find('ul').css('top').split('px')[0]) > maxTop){
						if(parseInt(container.find('ul').css('top').split('px')[0]) - container.find('li:first').innerHeight() > maxTop){
							container.find('ul').css('top',parseInt(container.find('ul').css('top').split('px')[0]) - optionArray.liHeight[e]);
							container.find('.scrollBar span').css('top',-( (parseInt(container.find('ul').css('top').split('px')[0]) * optionArray.scrollTop[e]) / optionArray.ulTop[e] ));
						}else{
							container.find('ul').css('top',maxTop);
							container.find('.scrollBar').find('span').css('top',optionArray.scrollTop[e]);
						}
					}
				}
				return false; // prevent default
			});
			container.find('.scrollBar').bind('mousewheel',function(event, delta, deltaX, deltaY) {
				if (delta > 0){
					/*to top*/
					var futureTop = parseInt(container.find('.scrollBar span').css('top').split('px')[0]) - container.find('.scrollBar span').innerHeight() / 4;
					(futureTop > 0) ? container.find('.scrollBar span').css('top',futureTop) : container.find('.scrollBar span').css('top',0);
				}else if (delta < 0){
					/*to bottom*/
					var futureTop = parseInt(container.find('.scrollBar span').css('top').split('px')[0]) + container.find('.scrollBar span').innerHeight() / 4;
					(futureTop < optionArray.scrollTop[e]) ? container.find('.scrollBar span').css('top',futureTop) : container.find('.scrollBar span').css('top',optionArray.scrollTop[e]);
				}
				container.find('ul').css('top', - (optionArray.ulTop[e] * parseInt(container.find('.scrollBar span').css('top').split('px')[0])) / optionArray.scrollTop[e] );
				return false; // prevent default
			});
			
			/*Click to close list*/
			$('body').click(function(){
				if (optionArray.click[e]==2){
					optionArray.click[e]=1;
				}else if(optionArray.click[e]==1){
					optionArray.click[e]=0;
					container.find('.scrollSelect').hide();
					container.find('.shownSelectOpened').removeClass('shownSelectOpened');
					container.find('.scrollBar span').css('top',0);
					container.find("ul").css('top',0);
				}
				
			});
		});
	};
	
})(jQuery);
