/*=========================================================
	MODULE zJsLayout
	----------------------------------------------------
	Bibliothèque de gestion des objets
=========================================================*/
import * as zLib from "./zJsLibrary.js";

export class LayoutManager {

	//===========================================================================================
	//		Constructor
	//===========================================================================================
	constructor(objLayoutStructure) {
		zLib.getXmlRoot(objLayoutStructure)
		.then(xmlRoot => {
			//console.log(xmlRoot);
			const parseError = xmlRoot.getElementsByTagName('parsererror');
			if (parseError.length) console.error('Error parsing XML layout:\n',parseError[0].innerText);
			
			let parent = null;
			// Identification du conteneur parent
			//if ($(xmlRoot).attr('containerId')) parent = $('#' + $(xmlRoot).attr('containerId'))[0];
			if(xmlRoot.hasAttribute('containerId')) parent = document.getElementById(xmlRoot.getAttribute('containerId'));
			// En l'absence de parent, une div dédiée est crée
			if(!parent) parent = document.createElement('div');

			// Analyse de la structure de construction
			this.#elmIterator(xmlRoot, parent);
			this.html = parent;
			this.uploadIndex = 0;
		})
		.catch((err) => console.error(err));

	}

	//===========================================================================================
	//		Iterator
	//===========================================================================================
	#elmIterator(xmlNode, parentDomNode, level=0) {
		//console.log('iterator:',xmlNode);
		
		// On ignore les noeuds texte ou commentaire
		if(xmlNode.nodeType !== 1) return;
		// On cérupère le nom de la balise
		const tagName = xmlNode.tagName;
		//console.log('tagName:', tagName);

		let domNode = null;
		// Test si la balise correspond à une fonction de construction
		let fn = "build"+tagName[0].toUpperCase()+tagName.slice(1);
		//console.log(`> function to call [${fn}]`);
		
		if(this[fn]) {
			domNode = this[fn](xmlNode, parentDomNode);
			if(parentDomNode && domNode) parentDomNode.appendChild(domNode);
		}

		// Parcourt récursivement les enfants
		for(let child of xmlNode.children) {
			this.#elmIterator(child, domNode || parentDomNode, level+1);
		}
	}





	//===========================================================================================
	//		Container
	//===========================================================================================
	buildContainer(obj, parent) {
		//console.log('> buildContainer called:', obj);
		
		// Conteneur
		const container = document.createElement('div');
		if(obj.id) container.id = obj.id;
		container.classList = "zContainer";
		if(obj.getAttribute('mode')=='vertical') container.classList.add("column");

		// Gestion du typage
		const containerType = (objType) => {
			for(const type of zLib.parseArray(objType)) {
				switch(type) {
					case "object":
						container.classList.add("zObj");			// margin right/bottom
						break;
					case "group":
						container.classList.add("zGrp");			// padding left/top
						break;
					case "outlined":
						container.classList.add("outlined");	// ...
						break;
					case "labelled":
						container.classList.add("zLbl");			// margin top
						break;
					case "topPadding":
						container.classList.add("zPad");			// padding top
						break;
					case "bottomPadding":
						container.classList.add("zMnu");			// padding bottom
						break;
					case "menu":
						container.classList.add("zMnu");			// padding bottom
						container.classList.add("column");		// Column
						break;
					case "groupOutlined":
						container.classList.add("zObj");
						container.classList.add("zGrp");
						container.classList.add("outlined");
						break;
					case "menuGroup":
						container.classList.add("zObj");
						container.classList.add("zGrp");
						container.classList.add("zMnu");
						container.classList.add("column");
						container.classList.add("outlined");
						break;
				}
			}
		}
		if(obj.hasAttribute('type')) containerType(obj.getAttribute('type'));

		if(obj.hasAttribute('label')) {
			container.classList.add("zLbl");
			container.setAttribute("data-label", obj.getAttribute('label'));
		}

		if(obj.hasAttribute('width')) container.style.width = obj.getAttribute('width');
		else container.style.grow = "1";
		if(obj.hasAttribute('grow')) container.style.flexGrow = obj.getAttribute('grow');
		if(obj.hasAttribute('height')) container.style.height = obj.getAttribute('height');

		// Intégration du conteneur principal dans le "parent" (si paramètre )
		if(parent) parent.appendChild(container);
		// Renvoi du conteneur principal
		return container;
	}

	//===========================================================================================
	//		Blank
	//===========================================================================================
	buildBlank(obj, parent) {
		//console.log('> buildBlank called:', obj);
		
		// Conteneur
		const container = document.createElement('div');
		switch(obj.getAttribute('mode')) {
			case "field":
				container.style.height = zLib.getCssRootVariable("--genericField-height");
				break;
			case "xsmall":
				container.style.height = zLib.getCssRootVariable("--spacing_xsmall");
				break;
			case "small":
				container.style.height = zLib.getCssRootVariable("--spacing_small");
				break;
			case "default":
				container.style.height = zLib.getCssRootVariable("--spacing_default");
				break;
			case "large":
				container.style.height = zLib.getCssRootVariable("--spacing_large");
				break;
			case "xlarge":
				container.style.height = zLib.getCssRootVariable("--spacing_xlarge");
				break;
			case "no-margin":
				break;
			default:
				container.classList = 'zObjectContainer';
				if(obj.getAttribute('mode')=="labelUp") container.classList.add("zLabelUp");
				container.style.height = zLib.getCssRootVariable("--genericField-height");
				break;
		}
		container.style.flexShrink = 0;
		if(obj.hasAttribute('width'))	container.style.width = obj.getAttribute('width');
		if(obj.hasAttribute('grow')) 	container.style.flexGrow = obj.getAttribute('grow');
		if(obj.hasAttribute('height')) container.style.height = zLib.extendedSizing(obj.getAttribute('height'));
		// Intégration du conteneur principal dans le "parent"
		parent.appendChild(container);
		// Renvoi du conteneur principal
		return container;
	}





	//===========================================================================================
	//		Button
	//===========================================================================================
	buildButton(obj, parent) {
		//console.log('> buildButton called:', obj);
		
		// Conteneur principal du champ
		const container = this.#buildObjectContainer(obj);

		// Libellé du champ
		const label = this.#buildLabel(obj);

		// ToolTip
		if (obj.hasAttribute('tooltip')) this.#buildTooltip(obj, container);

		// Champ de saisie principal
		const mainField = document.createElement('button');
		mainField.type = 'button';

		// id
		if(obj.id) mainField.id = obj.id;

		// Dimentions
		if(obj.hasAttribute('width')) mainField.style.width = obj.getAttribute('width');
		else mainField.style.flexGrow = 1;
		if(obj.hasAttribute('grow')) mainField.style.flexGrow = obj.getAttribute('grow');
		if(obj.hasAttribute('height')) mainField.style.height = zLib.extendedSizing(obj.getAttribute('height'));

		mainField.classList = 'zButton zButtonImageStd';
		if(obj.hasAttribute('onClick')) mainField.setAttribute('onclick', obj.getAttribute('onClick'));
		else {
			mainField.addEventListener('click', () => {
				window.postMessage({ action: "button", payload:{buttonId:obj.id, buttonText:mainField.textContent}}, "*");
			})
		}
		var buttonText;
		var shortKey;
		if(obj.hasAttribute('text')) {
			if(obj.getAttribute('text').includes("&")) {
				let tag = obj.getAttribute('text').indexOf("&");
				if(tag<obj.getAttribute('text').length) {
					if(obj.getAttribute('text')[tag+1]=="&") {
						buttonText = obj.getAttribute('text').slice(0,tag)+obj.getAttribute('text').slice(tag+1);
					} else {
						buttonText	= obj.getAttribute('text').slice(0,tag)+"<u>"+obj.getAttribute('text')[tag+1]+"</u>"+obj.getAttribute('text').slice(tag+2);
						shortKey		= obj.getAttribute('text')[tag+1].toLowerCase();
					}
				}
			} else buttonText = obj.getAttribute('text');
		} 
		if(obj.hasAttribute('image')) {
			const image = document.createElement('img');
			image.src = obj.getAttribute('image');
			if(obj.hasAttribute('imageRight')) {
				image.classList = "zIconzButtonImageRight";
				mainField.innerHTML = buttonText;
				mainField.appendChild(image);
			} else 
			if(obj.hasAttribute('imageLeft')) {
				image.classList = "zIconzButtonImageLeft";
				mainField.appendChild(image);
				mainField.innerHTML += buttonText;
			} else {
				image.classList = "zIconzButtonImage";
				mainField.appendChild(image)
			}
		} else mainField.innerHTML = buttonText;

		// Gestion de la shortKey
		if(shortKey) {
			document.addEventListener("keydown", (event) => {
				console.log(event);

				if(event.altKey && event.key.toLowerCase() === shortKey) {
					event.preventDefault();				// empêche un éventuel comportement par défaut
					mainField.click();					// simule un clic sur le bouton
				}
			})
		}
		// Intégration des éléments dans le conteneur principal
		container.appendChild(label);
		container.appendChild(mainField);
		// Intégration du conteneur principal dans le "parent"
		parent.appendChild(container);
		// Renvoi du conteneur principal
		return container;
	}





	//===========================================================================================
	//		Selector
	//===========================================================================================
	buildSelectList(obj, parent) {
		// Conteneur principal du champ
		const container = this.#buildObjectContainer(obj);
		// Libellé du champ
		const label = this.#buildLabel(obj);
		// Champ principal
		const mainField = document.createElement('select');
		// id et name (link)
		if(obj.id) mainField.id = obj.id;
		if(obj.hasAttribute('link'))	mainField.name = obj.getAttribute('link');
		// Dimentions
		if(obj.hasAttribute('width')) mainField.style.width = obj.getAttribute('width');
		else mainField.style.flexGrow = 1;
		mainField.style.minWidth = 0;
		if(obj.hasAttribute('grow')) mainField.style.flexGrow = obj.getAttribute('grow');

		mainField.classList = 'zSelectorField unselectable';

		if(obj.hasAttribute('extAttribute')) {
			const attribute = zLib.parseObject(obj.getAttribute('extAttribute'));
			Object.entries(attribute).forEach(([key, value]) => { mainField.setAttribute(key, value); });
		}
		
		const fillOption = async (mainfield, obj) => {
			// Génération des options
			let options=[];
			if(obj.hasAttribute('placeholder')) {
				options.push({value:'', text:obj.getAttribute('placeholder')});
			}
			// Options fournies en direct
			if(obj.hasAttribute('options')) {
				const optionList = zLib.parseObject(obj.getAttribute('options'));
				for(let key in optionList) options.push({value: key, text: optionList[key] });
			}
			
			// Options issues d'une requête
			if(obj.hasAttribute('request')) {
				const optionList = await zLib.dbQuery({query: obj.getAttribute('request')});
				for(let obj of optionList) { options.push(obj) }
			}

			// Parcours de la liste des options
			let index = 0
			for(let opt of options) {
				const option			= document.createElement('option');
				option.textContent	= opt.text;
				if(obj.hasAttribute('placeholder') && index==0) {
					option.value			= '';
					option.disabled		= true;
					option.selected		= true;
					option.hidden			= true;
					option.classList.add('placeholder');
				} else {
					option.value			= (opt.value)? opt.value : opt.text;
					option.textContent	= opt.text;
					option.classList.add('realOption');
				}

				mainField.appendChild(option);
				index++
			}
			if(obj.hasAttribute('placeholder')) {
				mainField.required	= true;
				mainField.classList.add('placeholder-active');

				mainField.addEventListener('change', () => {
					if(mainField.value==='') mainField.classList.add('placeholder-active');
					else mainField.classList.remove('placeholder-active');
				});
			}
		}

		fillOption(mainField, obj);

		// Intégration des éléments dans le conteneur principal
		container.appendChild(label);
		container.appendChild(mainField);
		// Intégration du conteneur principal dans le "parent"
		parent.appendChild(container);
		// Renvoi du conteneur principal
		return container;
	}

	#fillCombo(elmCombo, options, placeholder) {

	}




	//===========================================================================================
	//		Input Text
	//===========================================================================================
	buildTextInput(obj, parent) {
		//console.log('> buildInputText called:', obj);
		
		// Conteneur principal du champ
		const container = this.#buildObjectContainer(obj);
		// Libellé du champ
		const label = this.#buildLabel(obj);
		// Champ principal
		const mainField = document.createElement('input');
		if(obj.hasAttribute('type')) mainField.type = obj.getAttribute('type');
		else mainField.type = 'text';
		if(obj.id) mainField.id = obj.id;
		//if(obj.link && !obj.assisted) mainField.name = obj.link;
		if(obj.hasAttribute('link')) mainField.name = obj.getAttribute('link');

		if(obj.hasAttribute('width')) mainField.style.width = obj.getAttribute('width');
		else mainField.style.flexGrow = 1;
		if(obj.hasAttribute('grow')) mainField.style.flexGrow = obj.getAttribute('grow');

		mainField.setAttribute('autocomplete', 'off');
		if(obj.hasAttribute('extAttribute')) {
			const attribute = zLib.parseObject(obj.getAttribute('extAttribute'));
			Object.entries(attribute).forEach(([key, value]) => { mainField.setAttribute(key, value); });
		}

		// Intégration des éléments dans le conteneur principal
		container.appendChild(label);
		container.appendChild(mainField);

		if(obj.hasAttribute('more')) {
			const more = document.createElement('button');
			more.classList.add('zMore');
			more.innerText='⁝';
			//more.innerText='☰';
			container.appendChild(more);
		}

		// Champ de saisie assisté > Ajout d'une droplist
		if(obj.hasAttribute('assisted')) {
			const assisted = zLib.parseObject(obj.getAttribute('assisted'));
			const inpValue = document.createElement('input');
			inpValue.type = 'text';
			inpValue.hidden = true;
			//inpValue.name = obj.link;
			container.appendChild(inpValue);
			const dropList = document.createElement('div');
			dropList.classList = "zDropList hidden"
			// Récupération des valeurs qui seront présentées
			fetch('../PHP/_requestData.php?query='+encodeURIComponent(assisted.query))
			.then(response => response.json())
			.then(reply  => {
				if(reply.CR=="DONE") {
					// Inscription des valeurs possible dans les attributs de la droplist
					dropList.options = reply.data;
					//console.log(reply.data);
					container.appendChild(dropList);
				} else console.error(reply.CR);
			});

			if(assisted.trigger>2) {
				// =====================================================
				// Ecoute de évènements d'entrée dans le champ de saisie
				mainField.addEventListener('input', () => {
					//console.log('Function "showDroplist" called');
					if(mainField.value.length<assisted.trigger) {
						hideDroplist();
						return;
					}
					// Filtrage des valeurs possibles commencant par le contenu du champ de saisie
					const options = dropList.options.filter(option => option.text.toLowerCase().startsWith(mainField.value.toLowerCase()));
					// Remplissage de la droplist avec les valeurs possibles
					dropList.innerHTML = '';
					const exclude = ['text'];
					var index = 0
					options.forEach(option => { 
						const div = document.createElement('div');
						div.classList = "zDropListOption selectable";
						if(index===0) div.classList.add('selected');
						div.dataset.index = index++;
						div.innerHTML = option.text;
						const optionKeys = Object.keys(option).filter(key => !exclude.includes(key));
						if(optionKeys.length>0) optionKeys.forEach(key => { div.dataset[key] = option[key] });
						//console.log(div.dataset);
						dropList.appendChild(div);
					});

					// Ajout des listner pour le survol et la sélection des options
					const droplistChilds = dropList.childNodes;
					droplistChilds.forEach(child => {
						child.addEventListener('mouseover', () => {
							droplistChilds.forEach(c => c.classList.remove('selected'));
							child.classList.add('selected');
						});
						child.addEventListener('mousedown', () => {
							//console.log('click on proposal');
							validateProposal(child);
						});
					})

					// Affichage de la droplist
					dropList.classList.remove('hidden');
					const containerRect = container.getBoundingClientRect();
					//console.log("containerRect:", containerRect);
					
					//dropList.style.top = (containerRect.top + containerRect.height) + 'px';
					dropList.style.top = containerRect.height + 'px';
					dropList.style.width = containerRect.width + 'px';
				});

				// =====================================================
				mainField.addEventListener('keydown', (event) => {
					//console.log('Function "handleKeydown" called');
					if(mainField.value.length<2 || dropList.classList.contains('hidden')) return;
					const options = dropList.querySelectorAll('div');
					if(options.length==0) return;
					const prevOption = dropList.querySelector('div.selected');
					const index = parseInt(prevOption.dataset.index);
					
					if(event.key==="ArrowDown") {
						if(index<(options.length-1)) {
							prevOption.classList.remove('selected');
							dropList.querySelector(`div[data-index='${index+1}']`).classList.add('selected');
							event.preventDefault();
						}
					}
					else if(event.key==="ArrowUp") {
						if(index>0) {
							prevOption.classList.remove('selected');
							dropList.querySelector(`div[data-index='${index-1}']`).classList.add('selected');
							event.preventDefault();
						}
					}
					else if(event.key==="Enter") {
						validateProposal(prevOption);
					}
				});

				// =====================================================
				mainField.addEventListener('blur', hideDroplist );

				function validateProposal(elm) {
					//console.log(`function "validateOption" called with parameter [${elm.innerHTML}]`);
					mainField.value = elm.innerHTML;
					inpValue.value = elm.value ?? elm.innerHTML;
					//mainField.dataset = elm.dataset;
					hideDroplist();
				}

				function hideDroplist() {
					//console.log('Function "hideDroplist" called');
					if(!dropList.classList.contains('hidden')) {
						dropList.innerHTML = '';
						dropList.classList.add('hidden');
					}
				}

			} else {

				// Ecoute de évènements d'entrée dans le champ de saisie
				mainField.addEventListener('input', () => {
				// Filtrage des valeurs possibles commencant par le contenu du champ de saisie
				const options = dropList.options.filter(option => option.text.toLowerCase().startsWith(mainField.value.toLowerCase()));
				if(options.length==1) {
					mainField.value = options[0].text;
					inpValue.value = options[0].value;
				 };
				});
			}
		}	

		// Intégration du conteneur principal dans le "parent"
		parent.appendChild(container);
		// Renvoi du conteneur principal
		return container;
	}





	//===========================================================================================
	//		Input File (Upload)
	//===========================================================================================
	buildUploadInput(obj, parent) {
		//console.log('> buildUploadInput called:', obj);
		
		// Conteneur principal du champ
		const container = this.#buildObjectContainer(obj);
		// Libellé du champ
		const label = this.#buildLabel(obj);// Conteneur principal du champ
		// Champ principal
		const mainField = document.createElement('input');
		mainField.type = "file"
		if(obj.hasAttribute('id')) mainField.id = obj.id;

		if(obj.hasAttribute('width')) mainField.style.width = obj.getAttribute('width');
		else mainField.style.flexGrow = 1;
		if(obj.hasAttribute('grow')) mainField.style.flexGrow = obj.getAttribute('grow');

		if(obj.hasAttribute('format')) mainField.setAttribute('accept', obj.getAttribute('formats'));
		if(obj.hasAttribute('multiple')) mainField.setAttribute('multiple', true);

		if(obj.upload=="auto") {
			mainField.addEventListener("change", ()=> {
				// Liste des fichiers déposés
				const files = mainField.files;
				this.#uploadFiles(files);
			})
		}

		// Intégration des éléments dans le conteneur principal
		container.appendChild(label);
		container.appendChild(mainField);
		// Intégration du conteneur principal dans le "parent"
		parent.appendChild(container);
		// Renvoi du conteneur principal
		return container;
	}





	//===========================================================================================
	//		Upload container
	//===========================================================================================
	buildUploadContainer(obj, parent) {
		//console.log('> buildUploadContainer called:', obj);
		
		// Conteneur principal du champ
		const container = this.#buildObjectContainer(obj);
		// Libellé du champ
		const label = document.createElement('span');
		label.classList = "zInputLabelStyle unselectable";
		label.style.flexShrink = 0;
		label.innerHTML = obj.getAttribute('label');
		// Champ principal
		const mainField = document.createElement('div');
		if(obj.id) mainField.id = obj.id;

		mainField.classList = "zFlexCol zUploadContainer";
		if(obj.hasAttribute('width')) mainField.style.width = obj.getAttribute('width');
		else mainField.style.flexGrow = 1;

		// Empêcher le comportement par défaut (ouverture du fichier dans le navigateur)
		mainField.addEventListener('dragover', (e) => {
			e.preventDefault();
			mainField.classList.add('dragover');
		});

		mainField.addEventListener('dragleave', () => {
			mainField.classList.remove('dragover');
		});

		mainField.addEventListener('drop', (e) => {
			e.preventDefault();
			mainField.classList.remove('dragover');
			// Liste des fichiers déposés
			const files = e.dataTransfer.files;
			this.#uploadFiles(files);
		});

		// Intégration des éléments dans le conteneur principal
		mainField.appendChild(label);
		container.appendChild(mainField);
		// Intégration du conteneur principal dans le "parent"
		parent.appendChild(container);
		// Renvoi du conteneur principal
		return container;

	}

	#uploadFiles(files) {
		if (files.length === 0) return;
		// Création du FormData
		const formData = new FormData();
		// Ajout des fichier au FormData
		for (const file of files) {formData.append('files[]', file) }
		// Envoyer les fichiers au serveur
		//console.log("> Call php Upload script");
		//console.log("  formData:", formData);
		fetch('../php/_fileUpload.php', { method: 'POST', body: formData})
		.then(response => { 
			if(response.ok) return response.text();
			else window.postMessage({ action: "upload", payload: { CR:"error", errors:[{message:"Erreur exécution Upload"}]} }, "*");
		})
		.then(data => {
			// on averti la page de l'upload
			//console.log("> Send upload message to the page");
			window.postMessage({ action: "upload", payload: data}, "*");
		})
	}





	//===========================================================================================
	//		Input Currency
	//===========================================================================================
	buildCurrencyInput(obj, parent) {
		//console.log('> buildCurrencyInput called:', obj);
		
		// Conteneur principal du champ
		const container = this.#buildObjectContainer(obj);
		
		// Libellé du champ
		const label = this.#buildLabel(obj);// Conteneur principal du champ
		
		// Champ principal
		const mainField = document.createElement('input');
		mainField.type = 'text';
		if(obj.id) mainField.id = obj.id;
		if(obj.hasAttribute('link')) mainField.name = obj.getAttribute('link');
		mainField.classList.add('currencyInput');
		mainField.placeholder = '0,00';

		if(obj.hasAttribute('width')) mainField.style.width = obj.getAttribute('width');
		else mainField.style.flexGrow = 1;
		if(obj.hasAttribute('grow')) mainField.style.flexGrow = obj.getAttribute('grow');

		mainField.setAttribute('autocomplete', 'off');
		if(obj.hasAttribute('extAttribute')) {
			const attribute = zLib.parseObject(obj.getAttribute('extAttribute'));
			Object.entries(attribute).forEach(([key, value]) => { mainField.setAttribute(key, value); });
		}

		mainField.addEventListener('input', (e) => {
			let val = mainField.value;
			// Remplace les points par des virgules
			val = val.replace('.', ',');
			// Supprime tous les caractères sauf chiffres et virgule
			val = val.replace(/[^\d,]/g, '');
			// S'assurer qu’il n’y a qu’une seule virgule
			const parts = val.split(',');
			if (parts.length > 2) {
				val = parts[0] + ',' + parts[1]; // ignore les virgules suivantes
			}
			mainField.value = val;
		});
		mainField.addEventListener('blur', () => {
			let val = mainField.value;
			// Remplace la virgule par un point pour la conversion
			val = val.replace(',', '.');
			let number = parseFloat(val);
			if (isNaN(number)) {
			input.value = '';
			return;
			}
			// Formate avec espace comme séparateur de milliers et virgule comme séparateur décimal
			const formatted = number
			.toLocaleString('fr-FR', {
				minimumFractionDigits: 2,
				maximumFractionDigits: 2,
			});
			mainField.value = formatted;
		});

		// Intégration des éléments dans le conteneur principal
		container.appendChild(label);
		container.appendChild(mainField);
		// Intégration du conteneur principal dans le "parent"
		parent.appendChild(container);
		// Renvoi du conteneur principal
		return container;
	}





	//===========================================================================================
	//		Option (menu in a box)
	//===========================================================================================
	buildOption(obj, parent) {
		//console.log('> buildOption called:', obj);
		
		//console.log("BuildOption:", obj);

		// Conteneur principal du champ
		const container = document.createElement('div');
		container.style.grow = "1";

		// ToolTip
		if (obj.hasAttribute('tooltip')) this.#buildTooltip(obj, container);
		/*
		if(obj.hasAttribute('toolTip')) {
			container.dataset['tooltip'] = obj.getAttribute('toolTip');
			container.classList.add("tooltipHidden");
		}
		container.addEventListener('mouseover', () => {
			container.classList.add("tooltipHidden");
			setTimeout(() => {container.classList.remove("tooltipHidden");}, 3000);
		})
		*/
		// Champ principal
		const mainField = document.createElement('span');
		if(obj.id) mainField.id = obj.id;
		mainField.classList = "zMenuBOption unselectable";
		mainField.innerText = obj.innerHTML;
		if(obj.hasAttribute('onClick')) mainField.setAttribute('onclick',obj.getAttribute('onClick'));

		// Intégration des éléments dans le conteneur principal
		container.appendChild(mainField);
		// Intégration du  conteneur principal dans le "parent"
		parent.appendChild(container);
		// Renvoi du conteneur principal
		return container;
	}





	//===========================================================================================
	//		Text area
	//===========================================================================================
	buildTextArea(obj, parent) {
		// Conteneur principal du champ
		const container = this.#buildObjectContainer(obj);
		// Libellé du champ
		const label = this.#buildLabel(obj);// Conteneur principal du champ
		// Champ principal
		const mainField = document.createElement('textArea');
		if(obj.id) {
			mainField.id = obj.id;
			mainField.name = obj.id;
		}
		mainField.classList = 'frozen';
		if(obj.hasAttribute('extAttribute')) {
			const attribute = zLib.parseObject(obj.getAttribute('extAttribute'));
			Object.entries(attribute).forEach(([key, value]) => { mainField.setAttribute(key, value); });
		}

		// Intégration des éléments dans le conteneur principal
		container.appendChild(label);
		container.appendChild(mainField);
		// Intégration du  conteneur principal dans le "parent"
		parent.appendChild(container);
		// Renvoi du conteneur principal
		return container;
	}





	//===========================================================================================
	//		Checkbox
	//===========================================================================================
	buildCheckbox(obj, parent) {
		//console.log('> buildCheckbox called:', obj);
		
		// Conteneur principal du champ
		const container = this.#buildObjectContainer(obj);
		// Libellé du champ
		const label = this.#buildLabel(obj);// Conteneur principal du champ
		//if(obj.mode!="labelAfter") label.classList.add("zMgRs");
		//else label.classList.add("zMgL");
		// Champ principal
		const mainField = document.createElement('input');
		mainField.type  = 'checkbox';
		mainField.style.width = "16px";
		if(obj.id) mainField.id = obj.id;
		if(obj.hasAttribute('link')) mainField.name = obj.getAttribute('link');

		// Intégration des éléments dans le conteneur principal
		if(obj.getAttribute('mode')!="labelAfter") {
			container.appendChild(label);
			container.appendChild(mainField);
		} else {
			container.appendChild(mainField);
			container.appendChild(label);
		}
		
		// Intégration du  conteneur principal dans le "parent"
		parent.appendChild(container);
		// Renvoi du conteneur principal
		return container;
	}





	//===========================================================================================
	//		Object container (internal)
	#buildObjectContainer(obj) {
		//console.log('> #buildObjectContainer called:', obj);

		// Conteneur
		const container = document.createElement('div');
		container.classList = "zContainer";
		container.classList.add("zObj");
		if(obj.getAttribute('mode')=="labelUp" || obj.getAttribute('mode')=="labelDown") container.classList.add("zFlexCol");
		if(obj.getAttribute('mode')!="labelUp" && obj.getAttribute('mode')!="labelDown") container.classList.add("zVCenter");
		//if(obj.hasAttribute('width')) container.style.width = obj.getAttribute('width');
		//else container.style.grow = "1";
		if(obj.hasAttribute('grow')) container.style.flexGrow = obj.getAttribute('grow');
		if(obj.hasAttribute('height')) container.style.height = obj.getAttribute('height');
		return container;
	}

	//===========================================================================================
	//		Object Label (internal)
	#buildLabel(obj) {
		const label = document.createElement('span');
		label.classList = "zLabel unselectable";
		if(obj.hasAttribute('labelWidth')) label.style.width = obj.getAttribute('labelWidth');
		label.style.flexShrink = 0;
		var labelText = '';
		if(obj.hasAttribute('label')) labelText = obj.getAttribute('label');
		else {
			if(obj.hasChildNodes())	labelText = obj.childNodes[0].textContent;
			else labelText = obj.textContent;
		}
		if(labelText!='') {
			label.innerHTML = labelText;
			if(obj.getAttribute('mode')=="labelAfter") label.classList.add("right");
			else label.classList.add("left");
		} else {
			if(obj.getAttribute('mode')=="labelUp") label.classList.add("up");
			if(obj.getAttribute('mode')=="labelDown") label.classList.add("down");
		}
		return label;
	}

	#buildTooltip(obj, container) {
		container.dataset['tooltip'] = obj.getAttribute('tooltip');
		container.classList.add("tooltipHidden");
		// Listner de survol
		container.addEventListener('mouseover', () => {
			container.classList.add("tooltipHidden");
			setTimeout(() => {container.classList.remove("tooltipHidden");}, 2000);
		})
	}




	//===========================================================================================
	onButton(handler) {
		window.addEventListener("message", (event) => {
			//console.log("onMenu:",event.data);
			const { action, payload } = event.data;
			if ( action === "button") handler(payload);
		});
	}
	onUpload = (handler) => {
		window.addEventListener("message", (event) => {
			//console.log("onUpload:",event.data);
			const { action, payload } = event.data;
			if ( action === "upload") handler(JSON.parse(payload));
		});
	}


/* End of class FormManager */
}

export const fillComboWithRequest = (selectID, fillQuery, selected=null, firstChoice=null) => {
	console.log(`Fill combo '${selectID}' with "${fillQuery}"`);
	zLib.dbQuery({query:fillQuery})
	.then(reply  => {
		comboFillOptions(document.getElementById(selectID), reply, selected, firstChoice);
	});
}

export const comboFillOptions = (elmSelect, options, selected=null, firstChoice=null) => {
	console.log(`Fill combo '${elmSelect}' with "${options}"`);

	let option;
	
	// Purge des options existantes
	while(elmSelect.options.length >0) elmSelect.remove(0);
	// Option par défaut 
	if(firstChoice) {
		option = document.createElement('option');
		option.value		= '';
		option.text			= firstChoice;
		option.disabled	= true;
		option.selected	= true;
		option.hidden		= true;
		option.classList.add('placeholder');
		elmSelect.appendChild(option, null);
		elmSelect.required = true;
		elmSelect.classList.add('placeholder-active');

		elmSelect.addEventListener('change', () => {
			if(elmSelect.value==='') elmSelect.classList.add('placeholder-active');
			else elmSelect.classList.remove('placeholder-active');
		})

	}
	// Options disponibles
	options.forEach(item => {
		option = document.createElement('option');
		option.value = (item.value)? item.value : item.text;
		option.text = item.text;
		option.classList.add('realOption');
		if(item.filter) option.setAttribute('data-filter', item.filter);
		option.selected = (item.text==selected);
		elmSelect.appendChild(option);
	})
}

