/**
 * 
 * On recherche les éléments avec les clauses: <br/>
 * base_search_list, base_search_list_XXXX (XXXX: étant le nom de l'objet courant.<br/>
 * 
 * @class
 * @static
 * @name searchList
 * @version 1.0 
 */
(function($){
	$.fn.extend({
		searchList: function(extendConfiguration) {
//			return true;
			var globalConfiguration = $.extend({
				/* Objet sur leque sera ouvert la popinp */
				form_object: 'activated',
				/* Fonction à utiliser pour trouver le libellé d'une instance  */
				captionItem: boi18n.getMessage('/bov3/wcm','bov3_searchlist_item'),
				captionItems: boi18n.getMessage('/bov3/wcm','bov3_searchlist_items'),
				maxHeightList: 200, /* Taille maximale de la liste des valeurs */
				actionCssClass: 'small_action' /* Classe à utiliser pour l'action  */,
				actionCaption : boi18n.getMessage('/bov3/wcm','bov3_searchlist_more') /* Libelle de l'action */,
				defaultOptionIds : "" /* String 1,2,3 ou [1,2,3] ou ["1","2","3"]*/
			}, extendConfiguration);

			/* Méthode interne pour aller chercher les libelles manquants */
			retrieveCaptionFromId = function(form_object, form_id) {
				var result = form_object + "/" + form_id + " ??? ";
				$.ajax({
					url: boState.getContextPath()+'/bov3/common/actions/ajaxRetrieveCaptionFromId.jspz',
					data: {
						form_object: form_object,
						form_id: form_id
					},
					success: function(data) {
						result = data;
					},
					error: function() {
						result = "";
					},
					async:false
				});
				return result;
			};
			
			return this.each(function() {
				var objectLinked = $(this);
				if (objectLinked.attr('data-bov3-searchlist-div-associated')!=undefined) {
					/* déjà fait, on continue*/
					return true;
				}

				var configuration= $.extend(configuration, globalConfiguration, eval('('+objectLinked.attr('data-bov3-searchlist-options')+')'));

				/* On cache la cible */
				objectLinked.hide();

				/* on construit le template */
				var objectBase = $("<div></div>")
									.addClass("widget-bov3-searchlist-div")
									.css({margin:'0px',border:'0px',cursor: 'pointer'});

				var objectText = $("<div></div>").addClass("widget-bov3-searchlist-div-text").append( "<span></span>" );
				var objectChoice = $("<div></div>").addClass("widget-bov3-searchlist-div-choice").css({position: 'absolute',	'border-top-width': '0px'});
				var objectOptions = $("<div></div>").addClass("widget-bov3-searchlist-div-options").css({overflow: 'auto'});
				var objectAction = $("<div></div>").addClass("widget-bov3-searchlist-div-action");

				/* on construit l'action */
				var oneAction = $("<a></a>")
									.addClass( configuration.actionCssClass )
									.text(configuration.actionCaption);

				oneAction.click(function() {
					var tmp = objectLinked.val();
					if ($.isArray(tmp)) tmp = tmp.join(",");
					var params = {
						form_action: 'popinlist',
						form_object: configuration.form_object,
						baseWhere: 'base_search_list,base_search_list_'+configuration.form_object,
						selected: tmp };
					$(this).attr('href', boState.getContextPath()+ '/wcm.jspz?' + $.param(params));
					$(this).contribution({
						title: boi18n.getMessage('/bov3/wcm','bov3_searchlist_search'),
						onReturnValue: function(window, datas) {
							objectBase._removeOptions();
							var $names = $(datas.array_names);
							
							$.each( $(datas.array_ids), function(index, value) {
								var name = $names.get(index) ;
								objectBase._addOption(value, name, true);
							});
						}
					});
					return false;
				});


				objectAction.append( oneAction );

				objectChoice.append( objectOptions ).append( objectAction );
				objectBase.append( objectText ).append( objectChoice );

				objectLinked.attr('data-bov3-searchlist-div-associated','true');
				objectLinked.after( objectBase );

				/*
				 * Un changement de l'option elle-même sera notifié
				 */
				var checkbox_change = function() {
					objectBase._onchange();
				};

				objectBase.timeout = null;

				/*
				 * Si on clique en dehors alors on ferme immediatement
				 */
				objectBase._clickExternal = function(e) {
					var hide=true;
					var parent = objectBase.get(0);
					$(e.relatedTarget).parents().andSelf().each(function() {
						if( this == parent ) {
							hide = false;
							return;
						}
					});
					if( hide ) {
						objectBase._hide();
						if (objectBase.timeout!=null) objectBase.timeout=null;
					}
				}
				/*
				 * Si on entre dans le composant, alors on annule la fermeture de la liste
				 */
				objectBase._mouseover = function() {
					if (objectBase.timeout!=null) {
						window.clearTimeout(objectBase.timeout);
						objectBase.timeout=null;
					}
					objectBase.unbind('mouseover', objectBase._mouseover);
					$(document).unbind('click', objectBase._clickExternal);
				};

				/*
				 * Gestion de la disparition de la liste des options
				 * Si on sort du composant, alors on schedule la fermeture
				 * On surveille aussi tant que possible les clicks exterieurs pour fermer la liste plus rapidement
				 */
				objectBase.mouseout(function(e) {
					var hide=true;
					var parent = objectBase.get(0);
					$(e.relatedTarget).parents().andSelf().each(function() {
						if( this == parent ) {
							hide = false;
							return false;
						}
					});
					if( hide ) {
						$(document).bind('click', objectBase._clickExternal);
						objectBase.bind('mouseover', objectBase._mouseover);
						objectBase.timeout = window.setTimeout(objectBase._hide, 1000);
					}
					return true;
				});
				/*
				 * Gestion du resize de la liste des choix (avec actions)
				 * Pour ne pas dépasser une taille monstrueuse
				 */
				objectBase._resize = function() {
					if (!objectBase.activateResize) return;
					
					var divChoice = objectChoice;
					/* Ce n'est pas la peine de calculer la taille si invisible*/
					if (!divChoice.is(':visible')) return;

					var divOptions = objectOptions;
					/* On efface la hauteur fixée précédemment pour avoir la bonne taille */
					divOptions.css('height','');

					/* On gère une taille maximale sur les options */
					var options_height = divOptions.height();
					if (options_height>configuration.maxHeightList) {
						options_height=configuration.maxHeightList;
						divOptions.height( options_height );
					}

					/* La taille des options au final */
					options_height = divOptions.outerHeight(true);
					/* Hauteur de choix : taille de options + taille de action */
					divChoice.height( options_height + objectAction.outerHeight(true) );

					/* Largeur de choix : largeur de parent - border de choix */
					var new_width = objectBase.width();
					// il faut retirer nos border
					var border_width = divChoice.outerWidth(false)-divChoice.innerWidth();
					new_width = new_width - border_width;
					divChoice.width(new_width);
				};
				/*
				 * On affiche la liste :
				 * => repositionne la liste correctement
				 */
				objectBase._show = function(params) {
					objectChoice.show();
					objectBase._resize();
				};
				/*
				 * On cache la liste
				 */
				objectBase._hide = function(params) {
					objectChoice.hide(params);
				}
				/*
				 * On change l'affichage ou non de la liste
				 */
				objectBase._toggle = function(params) {
					if (objectChoice.is(':visible')) objectBase._hide(params);
					else objectBase._show(params);
				}
				/*
				 * Gestion du click  pour afficher ou masquer la liste
				 */
				objectText.click(function() {
					objectBase._toggle();
					return false;
				});
				objectBase.activateOnChange=true;
				objectBase.activateResize=true;
				/*
				 * Sur n'importe quel changement des options
				 * - on modifie la valeur de la cible
				 * - on change le libellé pour montrer combien d'items sont sélectionnés
				 */
				objectBase._onchange = function() {
					if (!objectBase.activateOnChange) return; 
					var ids = [];
					var caption = "";
					objectBase.find(".widget-bov3-searchlist-div-option input:checkbox:checked").each(function() {
						ids.push($(this).val());
						var text = $(this).parent().find("> span").text();
						if (text.length==0) text = ""+$(this).val();
						if (caption.length==0) caption = text;
						else caption += ", "+text;
					});
					objectLinked.val(ids);

					/* Essayons d'afficher les noms si il y a de la place */
					if (caption.length>0 && caption.length<30) objectText.find("span").text( caption );
					else {
						switch(ids.length) {
							case 0:
								objectText.find("span").text("");
								break;
							case 1:
								objectText.find("span").text("1 " + configuration.captionItem);
								break;
							default:
								objectText.find("span").text(ids.length + " " + configuration.captionItems);
						}
					}
				};
				var objectlinked_change = function() {
					objectBase._initValuesFromLinked();
				};
				/*
				 * Ajouter une option.
				 * - val : identifiant de l'item
				 * - text : libellé associé de l'item (si text n'est pas indiqué alors on utilisera la fonctione retrieveCaptionFromId(object, id)
				 * pour récupérer le libellé à afficher.
				 */
				objectBase._addOption = function(val, text, selected) {
					var div = objectOptions;

					if (val==null || val=='') return;
					
					var found=false;
					div.find(".widget-bov3-searchlist-div-option[optionid='"+val+"'] input").each(function() {
						found=true;
						if (selected) $(this).prop('checked',true);
						else $(this).prop('checked', false);
						objectBase._onchange();
						return;
					});
					if (found==true) return;

					/* Tant que possible, tous les acteurs doivent fournir le libelle, mais
					 * pour pleins de raisons techniques, cela n'est toujours pas fait.
					 * Donc allons chercher les libelles manquants 
					 */
					if (text==null) {
						text = retrieveCaptionFromId(configuration.form_object, val);
					}

					var t = $("<label style='display:block'></label>");
					/*
					 * on laisse la css
					 * t.hover(label_handlerin, label_handlerout);
					 * */
					var item = $("<input type='checkbox'/>");
					item.val(val);
					item.bind('change', checkbox_change);
					if (selected) item.attr('checked','checked');
					t.append( item );
					t.append( $("<span></span>").text( text) );
					var option = $("<div class='widget-bov3-searchlist-div-option'></div>");
					option.attr('optionid', val);
					option.append(t);
					div.append( option );
					
					/* si objectLinked est une textbox alors il n'y a rien à faire
					 * Mais si c'est une SELECT alors il faut creer l'option au cas où elle n'existe pas 
					 * */
					if (objectLinked.size()>0 && objectLinked[0].tagName.toLowerCase()=='select') {
						if (objectLinked.find("option[value='"+val+"']").size()==0) {
							/* l'option n'existe pas */
							objectLinked.append( $("<option></option>").text("txt:"+val).val(val) );
						}
					}
					
					objectBase._onchange();
					objectBase._resize();
				};
				/*
				 * On désélectionne toutes les entrées
				 */
				objectBase._removeOptions = function() {
					objectOptions.find("input").prop('checked', false);
					objectBase._onchange();
				};
				/*
				 * Lecture des valeurs depuis l'objet linké
				 */
				objectBase._initValuesFromLinked = function() {

					objectBase.activateOnChange = false;
					objectBase.activateResize = false;

					/* On commence par désactiver tout ce qui est là*/
					objectBase._removeOptions();

					/* Lecture des options du target si c'est un select */
					objectLinked.children('option').each(function() {
							var $option = $(this);
							if( $option.val() != '' ) objectBase._addOption($option.val(), $option.html(), this.selected);
					});
					
					/* Il est possible qu'il y ait des indentifiants en plus non présent en option */
					if (configuration.defaultOptionIds!=null) {
						var defopts = [];
						if (typeof(configuration.defaultOptionIds)=='string') {
							defopts = configuration.defaultOptionIds.split(",");
						} else defopts = configuration.defaultOptionIds;
						
						$.each( $(defopts), function(index, value) {
							objectBase._addOption(value, null, true);
						});
					}

					objectBase.activateOnChange = true;
					objectBase.activateResize=true;
					objectBase._onchange();
					objectBase._resize();
				}

				/* Premiere fois on cache la liste */
				objectLinked.bind('change', objectlinked_change);
				objectBase._hide();
				objectBase._initValuesFromLinked();

			});
		}
	});

	$(function(){
		/*if (typeof(console)!='undefined') console.log('searchlist init ...');*/
		$('select[data-bov3-searchlist-options]').searchList();
		/*if (typeof(console)!='undefined') console.log('searchlist init ended');*/
	});

})(jQuery);

