/*
 * listBuilder - jQuery Plugin
 * Simple list Builder
 *
 * Copyright (c) 2008 - 2011 Stephane Vasseur
 *
 * Version: 1.3.4 (11/11/2010)
 * Requires: jQuery v1.3+
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */

(function($) {
	var debugMode = true;
	
	var busy = false; 
	var inverse = false; 
	var allowDoublon = false;
	var leftScroll = true;
	var rightScroll = true;
	var cVessels = true;	
	var listBuilder = '';
	var leftList;
	var rightList;
	var rightType = 'select';
	var leftType = 'select'; // accept 'select' or 'checkbox' value
	// function bindAction(el){
	// 	debug("bindAction("+$(el).html()+")");
	// 	$(".action input[type='button'], .itemsToAdd option", el).click( function(event){
	// 		debug("$(this).click : "$(this).html());
	// 		if( $(this).is('.itemsToAdd option') ){
	// 			debug("$(this).is('option')");
	// 			$(".itemsToChoose", listBuilder).append($(this).clone());
	// 			$(this).remove();
	// 		}else{
	// 			var arr = $(this).attr("name").split("2");
	// 			var from = arr[0];
	// 			var to = arr[1];
	// 			$("." + from + " option:selected", listBuilder).each(function(){
	// 				$("." + to, listBuilder).append($(this).clone());
	// 				$(this).remove();
	// 			});
	// 		}
	// 		bindAction(el);
	// 		event.preventDefault()
	// 	});
	// };
	function debug(msg){
		if(window.console && console.debug && debugMode ){  console.debug(msg); }else if(window.console && console.log && debugMode ){ console.log(msg); }
	}
	function warning(msg){
		if(window.console && console.warn && debugMode ){  console.warn(msg); 
		}else if(window.console && console.error && debugMode ){ console.error(msg); 
		}else if(window.console && console.info && debugMode ){ console.info(msg); }
	}
	
	function isset () {
		var a = arguments, l = a.length, i = 0, undef;
		if (l === 0) { throw new Error('Empty isset'); };
		while (i !== l) { if (a[i] === undef || a[i] === null) { return false;  }; i++; }; return true;
	}
	
	/*
	*  Private Methods
	*/
	function switchOption(el){
		if(debugMode){ try{ console.groupCollapsed( "function switchOption(el:"+el+")" ); }catch(e){}; };
		debug("el.html :\n> "+ $(el).html() );
		
		var arr = "";
		debug( "$(el).parent():"
		+ $(el).parents(".right2left, .left2right")+":"+ $(el).parents(".right2left, .left2right").length
		+ ",  parent rel isset ?"+isset($(el).parents(".right2left, .left2right").attr("rel")) 
		+ "");
		
		var l = $(el).parents(".right2left, .left2right");
		if ( isset( $(l).attr("rel") ) && $(l).attr("rel").match(/2/)) {
			arr = $(l).attr("rel").split("2");
		}else{
			warning("targeted list undefined : no rel attribute parents")
			alert("targeted list undefined : no rel attribute parents");
		}
		var from = arr[0];
		var to = arr[1];
		debug( "from:" + from + ", to:"+ to );
		
		debug("listBuilder = "+listBuilder);
		debug("$('."+ from + " option:selected', listBuilder) = " + $("." + from + " option:selected", listBuilder).length );
		if( $(el).is('option') ){
			debug("$(el).is('option')");
			moveOption(el, from, to);
		}else{
			debug("$(el).isnot('option')");
			$("." + from + " option:selected", listBuilder).each(function(){
				moveOption(this, from, to);
			});
		}
		if(debugMode){ try{ console.groupEnd(); }catch(e){}; };
	}
	
	
	function moveOption(el, from, to){
		if(debugMode){ try{ console.group("function moveOption(el, from, to)"); }catch(e){}; };
		
		var $from = $("."+from , listBuilder);
		var $to = $("."+to , listBuilder);
		var optValue = "";		// item value
		var optText = "";		// item label
		var newEl="";			// HTML to append to list
		
		if(debugMode){ try{ console.groupCollapsed("$(el)"); }catch(e){}; };
			debug(" $(el) { " + 
				"\n   id : "+$(el).attr('id') +
				"\n   class : "+$(el).attr('class') +
				"\n   select : "+$(el).is('select') +
				"\n   option : "+$(el).is('option') +
				"\n   el value : "+$(el).val() +
				"\n   div : "+$(el).is('div') +
				"\n   el text : "+$(el).text() +
				"\n   checkbox : "+$(el).is('.checkbox') +
				"\n   el checkbox value : "+$("input:checkbox",el).val() +
				"\n   optValue : "+ optValue +
				"\n } "
			);
		if(debugMode){ try{ console.groupEnd(); }catch(e){}; };

		if( $(el).is('option') ){
			optValue = $(el).val();
			optText =  $(el).text();
		}else{
			optValue = $("option, input", el).val();
			optText =  $("label", el).text() || $(el).text();
		}
		
		if (rightType == leftType && rightType == "select" ) {
			newEl = $(el).clone().attr('selected','').css({'background-color':'transparent'});
		}else{
			switch(rightType){
				case 'select': 
					newEl = "<option value='optValue' selected='selected'>"; 
				break;
				case 'checkbox': 
					newEl = "<li class='input checkbox'><input type='checkbox' name='"+$to.attr('id')+"' value='"+optValue+"' checked='checked'><label>"+optText+"</label></li>";
				break;
			}
		}
		// si l'élément n'estpas deja dans la liste
		if( $("*[value='" + optValue + "']", $to).length <= 0 && allowDoublon == false ){
			$to.append(newEl);
		}
		debug("$to option[value='" + optValue + "'].selected : " + $("option[value='" + optValue + "']", $to).attr("selected") );
		debug("$to input[value='" + optValue + "'].selected : " + $("input[value='" + optValue + "']", $to).attr("selected") );
		debug("$to input[value='" + optValue + "'].checked : " + $("input[value='" + optValue + "']", $to).attr("checked") );
		
		debug("cVessels = "+ cVessels );
		
		if( ( cVessels && !$(el).is('select') ) || $(el).is('.right2left option') ){  
			$(el).remove();
		}
		if(debugMode){ try{ console.groupEnd(); }catch(e){}; };
	}
	
	
	/*
	 * Public methods 
	 */
	$.fn.listBuilder = function(options) {
		if(debugMode){ try{ console.group("$.listBuilder = function("+options+")"); }catch(e){}; };
		
		var opts, itemsToAdd, action, add_btn, remove_btn, selectorId;
		var settings = {
			'cVessels' 	: 	true,
			'allowDoublon' : false,
			'inverse' 	: 	false,
			'add_btn' : true,
			'remove_btn': true,
			'beforeRight': '',
			'afterRight': '',
			'targetType' : 'select',
			'selector' : 'select',
			'targetScroll' : false,
			'sourceScroll' : false,
			'defaultItem' : -1 
		};
		if (busy) {
			return;
		}
		busy = true;
		
		// Context : listBuilder
		listBuilder = this;
		
		// initialize options
		opts = typeof arguments[1] !== 'undefined' ? arguments[1] : {}; // var opts = options
		try{ 
			debug("listBuilder opts="+opts); 
		}catch(err){
			debug("error on listBuilder.opts{}"+err); 
		}
		if ( options ) { 
			$.extend( settings, options );
			opts = options;
		}
		cVessels = opts['cVessels'];
		cVessels = opts['allowDoublon'];
		inverse = opts['inverse'];
		rightType = opts['targetType'];
		selector = opts['selector'];
		// define leftType
		if( $(selector, listBuilder).is('select') ){ leftType = "select"; }
		else if( $(selector, listBuilder).is('input:') ){  leftType = "checkbox"; }
		debug("leftType = "+leftType);
		
		
		if(debugMode){ try{
			console.groupCollapsed(".listBuilder");
			debug("listBuilder = "+listBuilder.html());
			console.groupEnd();
		}catch(e){}; };
		
		// left is the list from wich to choose option 
		$(selector, listBuilder).addClass('left');
		selectorId = $(selector, listBuilder).attr("id");
		if( $(selector, listBuilder).attr('scrolling') == undefined ){
			if( opts['sourceScroll'] ){
				$(selector, listBuilder).attr('scrolling', 'yes');
			}else{
				$(selector, listBuilder).attr('scrolling', 'no');
			}
		}
		
		itemsToAdd = opts['beforeRight'];
		switch(rightType){
			case 'select':
				var tScroll = ((opts['targetScroll'])? "scrolling='yes'" : "scrolling='no'");
				itemsToAdd = itemsToAdd + "<select name='"+selectorId+"' class='right' multiple='multiple' "+scrolling+" ></select>"; 
			break;
			case 'checkbox':
				itemsToAdd = itemsToAdd + "<ul class='right' ></ul>";
			break;
		}
		itemsToAdd = itemsToAdd + opts['afterRight'];
		
		if( add_btn==true || remove_btn==true  ){
			action = "<div class='input action'></div>";
		}
		
		
		debug("itemsToAdd = "+itemsToAdd);
		debug("action = "+action);
		debug("inverse = "+inverse);
		if( inverse ){
			$( itemsToAdd + action ).prependTo( $(this) );
		}else{
			$( action + itemsToAdd ).appendTo( $(this) );
		}
		
		add_btn = opts.add_btn;
		debug( "add_btn : " + add_btn );
		if( add_btn == false ){
			add_btn = $('.left', this);
		}else{
			if( add_btn == true || $(add_btn).length <= 0 ){
				add_btn = "<input name='left2right' class='left2right' rel='left2right' value='+ add' type='button'>"; 
				$(add_btn).appendTo( $( ".action", this) );
			}
		}
		$(add_btn).addClass('left2right').attr('rel', 'left2right');
		
		remove_btn = opts.remove_btn;
		debug( "remove_btn : " + remove_btn );
		if( remove_btn == false ){
			remove_btn = $('.right', this);
		}else{
			if( remove_btn == true ){
				remove_btn = "<input name='right2left' id='right2left' rel='right2left' value='- remove' type='button'>";
				$(remove_btn).appendTo( $( ".action", this) );
			}
		}
		$(remove_btn).addClass('right2left').attr('rel', 'right2left');
		
		if(debugMode){ try{
			console.groupCollapsed("add_btn"); 
			debug( "add_btn {id:" + $(add_btn).attr("id") +"; class:"+ $(add_btn).attr("class") +"; rel:"+ $(add_btn).attr("rel") + "}" );
			console.groupEnd();
			console.groupCollapsed("remove_btn");
			debug( "remove_btn {id:" + $(remove_btn).attr("id") +"; class:"+ $(remove_btn).attr("class") +"; rel:"+ $(remove_btn).attr("rel") + "}" );
			console.groupEnd();
		}catch(e){}; };
		
		debug("opts['rightScroll'] = "+opts['rightScroll']);
		if( opts['rightScroll'] == false ){
			$('.right2left', this).attr({ scrolling : 'no'}).css({ 'height':'auto' });
		}
		debug("opts['leftScroll'] = "+opts['leftScroll']);
		if( opts['leftScroll'] == false ){
			$('.left2Right', this).attr({ scrolling : 'no'}).css({ 'height':'auto' });
		} 
		
		debug("$('select.left',this).hasClass('valid') : "+$('select.left',this).hasClass('valid') );
		if( $('.left',this).hasClass('valid') ){
			debug("switch 'valid' class from .left to .right");
			$('.left',this).removeClass('valid');
			$('.right',this).addClass('valid');
		}
		
		var leftId = $('.left',this).attr('id');
		var leftName = $('.left',this).attr('name');
		debug("listId : "+ leftId +"\n listName : "+ leftId);
		
		$('.left', this).attr({ name:'dump', id:'dump' });
		$('.right', this).attr({ name:leftName, id:leftId });
		
		$('select', this).unbind('click');
		// $('.right2left, .left2right')
		
		// $.each(map, function(key, value) {
		if(debugMode){ try{
			console.groupCollapsed(".left2right.html()");
			debug('.left2right : ' + $('.left2right').html() );
			console.groupEnd(); 
		}catch(e){}; };
		
		// default item
		if(opts['defaultItem']){
			
		}
		
		if( opts['defaultItem'] >= 0 ){
			switchOptions();
		}
		
		$('.right2left, .left2right', listBuilder).each( function() { 
		// $.each( map, function(key, value) { 
			// if($("."+key, listBuilder).is('select')){
			if($(this).is('select')){
				$(this).bind( "change select",
					function(event){
						event.preventDefault();
						debug(" !! event:"+event.type+" !! ");
						switchOption($(":selected",this));
						return false;
					}
				);
			}else{
				$("> *",this).bind("click",
					function(event){
						event.preventDefault();
						debug(" !! event click :"+event.type+" !! ");
						switchOption(this);
						return false;
					} 	
				);
			}
		});
		
		
		busy = false;
		if(debugMode){ try{ debug("CLOSE listBuilder consoleGroup"); console.groupEnd(); }catch(e){}; };
	};

})( jQuery ); 
