/* BdfServer_Html - Copyright (c) 2010-2025 Vincent Calame - Exemole
 * Logiciel libre donné sous triple licence :
 * 1) selon les termes de la CeCILL V2
 * 2) selon les termes de l’EUPL V.1.1
 * 3) selon les termes de la GNU GPLv3
 * Voir le fichier licences.txt
 */


package fr.exemole.bdfserver.html.forms;

import fr.exemole.bdfserver.api.BdfServerConstants;
import fr.exemole.bdfserver.api.ficheform.AddendaIncludeElement;
import fr.exemole.bdfserver.api.ficheform.AlbumIncludeElement;
import fr.exemole.bdfserver.api.ficheform.CorpusIncludeElement;
import fr.exemole.bdfserver.api.ficheform.FormElement;
import fr.exemole.bdfserver.api.ficheform.ThesaurusIncludeElement;
import fr.exemole.bdfserver.api.interaction.domains.PiocheDomain;
import fr.exemole.bdfserver.api.namespaces.CellSpace;
import fr.exemole.bdfserver.html.consumers.FicheForm;
import fr.exemole.bdfserver.html.consumers.attributes.InputPattern;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import net.fichotheque.FichothequeConstants;
import net.fichotheque.addenda.Document;
import net.fichotheque.addenda.Version;
import net.fichotheque.album.Illustration;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.exportation.table.Cell;
import net.fichotheque.exportation.table.CellConverter;
import net.fichotheque.exportation.table.ColDef;
import net.fichotheque.thesaurus.Motcle;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.utils.CorpusMetadataUtils;
import net.fichotheque.utils.FichothequeUtils;
import net.mapeadores.util.attr.Attribute;
import net.mapeadores.util.html.HA;
import net.mapeadores.util.html.HtmlAttributes;
import net.mapeadores.util.html.HtmlConstants;
import net.mapeadores.util.html.HtmlPrinter;
import net.mapeadores.util.html.HtmlTableWriter;
import net.mapeadores.util.html.HtmlWrapper;
import net.mapeadores.util.html.WrapperFactory;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.UserLangContext;


/**
 *
 * @author Vincent Calame
 */
public final class IncludeFormHtml {

    private final static HtmlWrapper DOCUMENT_INPUT_CELL = WrapperFactory.div(HA.attr("data-ficheform-role", "document-input").classes("ficheform-standard-Cell"));
    private final static HtmlWrapper DOCUMENT_FILE_CELL = WrapperFactory.div(HA.attr("data-ficheform-role", "document-file").classes("ficheform-standard-Cell ficheform-document-FileCell"));
    private final static HtmlWrapper ILLUSTRATION_INPUT_CELL = WrapperFactory.div(HA.attr("data-ficheform-role", "illustration-input").classes("ficheform-standard-Cell"));
    private final static HtmlWrapper ILLUSTRATION_FILE_CELL = WrapperFactory.div(HA.attr("data-ficheform-role", "illustration-file").classes("ficheform-standard-Cell ficheform-illustration-FileCell"));
    private final static HtmlWrapper ENUMERATION_CELL = WrapperFactory.div(HA.attr("data-ficheform-role", "cell-enumeration").classes("ficheform-standard-Cell ficheform-MultiRows"));
    private final static HtmlWrapper ENUMERATION_CELL_EMPTY = WrapperFactory.div(HA.attr("data-ficheform-role", "cell-enumeration").classes("ficheform-standard-Cell ficheform-MultiRows hidden"));
    private final static HtmlWrapper FICHE_DIRECTINPUT_CELL = WrapperFactory.div(HA.attr("data-ficheform-role", "fiche-directinput").classes("ficheform-standard-Cell"));
    private final static HtmlWrapper MULTIROWS_FICHE_DIRECTINPUT_CELL = WrapperFactory.div(HA.attr("data-ficheform-role", "fiche-directinput").classes("ficheform-standard-Cell ficheform-MultiRows"));
    private final static HtmlWrapper MOTCLE_INPUT_CELL = WrapperFactory.div(HA.attr("data-ficheform-role", "motcle-input").classes("ficheform-standard-Cell"));
    private final static HtmlWrapper MULTIROWS_MOTCLE_INPUT_CELL = WrapperFactory.div(HA.attr("data-ficheform-role", "motcle-input").classes("ficheform-standard-Cell ficheform-MultiRows"));


    private IncludeFormHtml() {
    }

    public static boolean print(HtmlPrinter hp, FormElement.Include formElement, FormHandler formHandler) {
        if (formElement instanceof ThesaurusIncludeElement.Text) {
            printTextThesaurusInclude(hp, (ThesaurusIncludeElement.Text) formElement, formHandler);
        } else if (formElement instanceof ThesaurusIncludeElement.Choice) {
            printListThesaurusInclude(hp, (ThesaurusIncludeElement.Choice) formElement, formHandler);
        } else if (formElement instanceof ThesaurusIncludeElement.Hidden) {
            printHiddenInclude(hp, (ThesaurusIncludeElement.Hidden) formElement, formHandler);
        } else if (formElement instanceof ThesaurusIncludeElement.NotEditable) {
            printNotEditableThesaurusInclude(hp, (ThesaurusIncludeElement.NotEditable) formElement, formHandler);
        } else if (formElement instanceof ThesaurusIncludeElement.FicheStyle) {
            printFicheStyleThesaurusInclude(hp, (ThesaurusIncludeElement.FicheStyle) formElement, formHandler);
        } else if (formElement instanceof CorpusIncludeElement.Check) {
            printCheckCorpusInclude(hp, (CorpusIncludeElement.Check) formElement, formHandler);
        } else if (formElement instanceof CorpusIncludeElement.Table) {
            printTableCorpusInclude(hp, (CorpusIncludeElement.Table) formElement, formHandler);
        } else if (formElement instanceof AlbumIncludeElement) {
            printAlbumInclude(hp, (AlbumIncludeElement) formElement, formHandler, false);
        } else if (formElement instanceof AddendaIncludeElement) {
            printAddendaInclude(hp, (AddendaIncludeElement) formElement, formHandler, false);
        } else {
            return false;
        }
        return true;
    }

    public static boolean printAddendaInclude(HtmlPrinter hp, AddendaIncludeElement formElement, FormHandler formHandler, boolean withFileForm) {
        String name = formHandler.getPrefixedName(formElement);
        String addendaName = formElement.getAddenda().getSubsetName();
        List<Document> documentList = formElement.getDocumentList();
        hp
                .SECTION(formHandler.getEntryAttributes(formElement, "addenda-include").attr("data-subset-name", addendaName))
                .__(CommonFormHtml.printStandardLabel(hp, formElement, formHandler.getWorkingLang(), null))
                .__(getEnumerationCell(documentList.isEmpty()), () -> {
                    hp.DIV(HA.attr("data-ficheform-role", "document-list").classes("ficheform-Ordered"));
                    for (Document document : documentList) {
                        int documentId = document.getId();
                        hp
                                .DIV(HA.id(hp.generateId()).attr("data-ficheform-role", "document").classes("ficheform-document-Block").attr("data-subset-item-id", String.valueOf(documentId)))
                                .SPAN(HA.attr("data-ficheform-role", "document-uri").classes("ficheform-document-Uri"))
                                .__escape(document.getGlobalId())
                                ._SPAN()
                                .__dash()
                                .SPAN(HA.attr("data-ficheform-role", "document-basename").classes("ficheform-document-Basename"))
                                .__escape(document.getBasename())
                                ._SPAN()
                                .__space()
                                .SPAN(HA.attr("data-ficheform-role", "document-extensions").classes("ficheform-document-Extensions"))
                                .__escape("[ ");
                        boolean next = false;
                        for (Version version : document.getVersionList()) {
                            if (next) {
                                hp
                                        .__escape(" / ");
                            } else {
                                next = true;
                            }
                            String extension = version.getExtension();
                            hp
                                    .A(HA.href("documents/" + addendaName + "/" + document.getBasename() + "." + extension).target(HtmlConstants.BLANK_TARGET))
                                    .__escape('.')
                                    .__escape(extension)
                                    ._A();
                        }
                        hp
                                .__escape(" ]")
                                ._SPAN()
                                ._DIV();
                    }
                    hp._DIV();
                })
                .__(DOCUMENT_INPUT_CELL, () -> {
                    hp
                            .INPUT(hp.name(name + ":create").type(HtmlConstants.HIDDEN_TYPE).attr("data-ficheform-role", "createfield"))
                            .INPUT(hp.name(name + ":remove").type(HtmlConstants.HIDDEN_TYPE).attr("data-ficheform-role", "removefield"))
                            .INPUT(hp.name(name + ":change").type(HtmlConstants.HIDDEN_TYPE).attr("data-ficheform-role", "changefield"))
                            .INPUT(hp.name(name + ":order").type(HtmlConstants.HIDDEN_TYPE).attr("data-ficheform-role", "orderfield"));
                    if (formElement.isAddAllowed()) {
                        hp
                                .INPUT(hp.name(name + ":add").type(HtmlConstants.HIDDEN_TYPE).attr("data-ficheform-role", "addfield"));
                    }
                });
        if (withFileForm) {
            hp
                    .__(DOCUMENT_FILE_CELL, () -> {
                        HtmlAttributes fileInput = hp.name(name + ":file").type(HtmlConstants.FILE_TYPE).addClass("ficheform-Full global-FileInput").size("70").multiple(true);
                        hp
                                .LABEL_for(fileInput.id())
                                .__localize("_ label.edition.documentfileinput")
                                .__colon()
                                ._LABEL()
                                .DIV()
                                .INPUT(fileInput)
                                ._DIV();
                    });
        }
        hp
                ._SECTION();
        return true;
    }

    public static boolean printAlbumInclude(HtmlPrinter hp, AlbumIncludeElement formElement, FormHandler formHandler, boolean withUploadForm) {
        String name = formHandler.getPrefixedName(formElement);
        String albumName = formElement.getAlbum().getSubsetName();
        List<Illustration> illustrationList = formElement.getIllustrationList();
        hp
                .SECTION(formHandler.getEntryAttributes(formElement, "album-include")
                        .attr("data-subset-name", albumName))
                .__(CommonFormHtml.printStandardLabel(hp, formElement, formHandler.getWorkingLang(), null))
                .__(getEnumerationCell(illustrationList.isEmpty()), () -> {
                    hp.DIV(HA.attr("data-ficheform-role", "illustration-list").classes("ficheform-Ordered"));
                    for (Illustration illustration : illustrationList) {
                        int illustrationId = illustration.getId();
                        hp
                                .DIV(HA.id(hp.generateId()).classes("ficheform-illustration-Block").attr("data-ficheform-role", "illustration").attr("data-subset-item-id", String.valueOf(illustrationId)))
                                .DIV("ficheform-illustration-Image")
                                .IMG(HA.src("illustrations/_mini/" + illustration.getFileName()).attr("data-ficheform-role", "illustration-image"))
                                ._DIV()
                                .DIV(HA.attr("data-ficheform-role", "illustration-uri").classes("ficheform-illustration-Uri"))
                                .__escape(albumName + "/" + illustrationId)
                                ._DIV()
                                ._DIV();
                    }
                    hp._DIV();
                })
                .__(ILLUSTRATION_INPUT_CELL, () -> {
                    hp
                            .INPUT(HA.type(HtmlConstants.HIDDEN_TYPE).name(name + ":create").attr("data-ficheform-role", "createfield"))
                            .INPUT(HA.type(HtmlConstants.HIDDEN_TYPE).name(name + ":remove").attr("data-ficheform-role", "removefield"))
                            .INPUT(HA.type(HtmlConstants.HIDDEN_TYPE).name(name + ":update").attr("data-ficheform-role", "updatefield"));
                });
        if (withUploadForm) {
            hp
                    .__(ILLUSTRATION_FILE_CELL, () -> {
                        HtmlAttributes fileInput = hp.name(name + ":file").type(HtmlConstants.FILE_TYPE).addClass("ficheform-Full global-FileInput").size("70").multiple(true).attr("accept", "png,jpg,jpeg,bmp,gif");
                        hp
                                .LABEL_for(fileInput.id())
                                .__localize("_ label.edition.illustrationfileinput")
                                .__colon()
                                ._LABEL()
                                .SPAN("ficheform-illustration-Info")
                                .__localize("_ info.album.illustrationformat")
                                ._SPAN()
                                .DIV()
                                .INPUT(fileInput)
                                ._DIV();
                    });
        }
        hp
                ._SECTION();
        return true;
    }

    public static boolean printHiddenInclude(HtmlPrinter hp, ThesaurusIncludeElement.Hidden formElement, FormHandler formHandler) {
        String name = formHandler.getPrefixedName(formElement);
        hp
                .INPUT_hidden(name, formElement.getValue());
        return true;
    }

    public static boolean printCheckCorpusInclude(HtmlPrinter hp, CorpusIncludeElement.Check formElement, FormHandler formHandler) {
        String corpusName;
        String entryType;
        Corpus corpus = formElement.getCorpus();
        boolean withFicheId;
        if (corpus != null) {
            corpusName = corpus.getSubsetName();
            entryType = "corpus-include";
            withFicheId = true;
        } else {
            corpusName = null;
            entryType = "liage";
            withFicheId = false;
        }
        String name = formHandler.getPrefixedName(formElement);
        String genId = hp.generateId();
        hp
                .SECTION(formHandler.getEntryAttributes(formElement, entryType)
                        .attr("data-ficheform-limit", "-1")
                        .attr((!formElement.hasWeightFilter()), "data-ficheform-withweight", "1")
                        .attr("data-subset-name", corpusName)
                        .attr("data-ficheform-mode", "check"))
                .__(CommonFormHtml.printStandardLabel(hp, formElement, formHandler.getWorkingLang(), genId))
                .__(printFicheList(hp, formElement, name, formHandler.getUserLangContext(), withFicheId))
                .__(printDirectInput(hp, name, genId, formElement))
                ._SECTION();
        return true;
    }

    public static boolean printTableCorpusInclude(HtmlPrinter hp, CorpusIncludeElement.Table formElement, FormHandler formHandler) {
        Corpus corpus = formElement.getCorpus();
        String corpusName = corpus.getSubsetName();
        String name = formHandler.getPrefixedName(formElement);
        String genId = hp.generateId();
        hp
                .SECTION(formHandler.getEntryAttributes(formElement, "corpus-include")
                        .attr("data-ficheform-limit", "-1")
                        .attr("data-subset-name", corpusName)
                        .attr("data-ficheform-mode", "table"))
                .__(CommonFormHtml.printStandardLabel(hp, formElement, formHandler.getWorkingLang(), genId))
                .__(printFicheTable(hp, formElement, name, formHandler.getUserLangContext()))
                .__(printCorpusDirectInput(hp, name, genId))
                ._SECTION();
        return true;
    }

    private static boolean printDirectInput(HtmlPrinter hp, String name, String inputId, CorpusIncludeElement.Check formElement) {
        if (formElement.getCorpus() != null) {
            return printCorpusDirectInput(hp, name, inputId);
        } else {
            return printLiageDirectInput(hp, name, inputId, formElement);
        }
    }

    private static boolean printCorpusDirectInput(HtmlPrinter hp, String name, String inputId) {
        hp
                .__(FicheForm.STANDARD_CELL, () -> {
                    hp
                            .DIV(HA.attr("data-ficheform-role", "searchcontainer").classes("ficheform-search-Container"))
                            .DIV(HA.attr("data-ficheform-role", "fiche-directinput").classes("ficheform-search-DirectInput"))
                            .INPUT_text(HA.name(name).id(inputId)
                                    .attr("data-ficheform-role", "textinput")
                                    .classes("global-PlaceholderOnFocus ficheform-Full")
                                    .size("14")
                                    .populate(InputPattern.IDLIST)
                                    .attr("placeholder", hp.getLocalization("_ label.edition.directinput")))
                            ._DIV()
                            ._DIV();
                });
        return true;
    }

    private static boolean printLiageDirectInput(HtmlPrinter hp, String name, String inputId, CorpusIncludeElement.Check formElement) {
        HtmlAttributes inputAttributes = HA.name(name).id(inputId).attr("data-ficheform-role", "textinput").classes("ficheform-Medium");
        int rows = formElement.getRows();
        if (rows == 1) {
            hp
                    .__(FICHE_DIRECTINPUT_CELL, () -> {
                        hp
                                .INPUT_text(inputAttributes.size("29"));
                    });
        } else {
            hp
                    .__(MULTIROWS_FICHE_DIRECTINPUT_CELL, () -> {
                        hp
                                .TEXTAREA(inputAttributes.cols(39).rows(rows).attr("spellcheck", "false"))
                                ._TEXTAREA();
                    });
        }
        return true;
    }


    public static boolean printTextThesaurusInclude(HtmlPrinter hp, ThesaurusIncludeElement.Text formElement, FormHandler formHandler) {
        String name = formHandler.getPrefixedName(formElement);
        String thesaurusName = formElement.getThesaurus().getSubsetName();
        String widthType = formElement.getWidthType();
        int defaultSize = CommonFormHtml.getDefaultSize(widthType);
        String genId = hp.generateId();
        HtmlAttributes inputAttr = HA.name(name).id(genId).classes(CommonFormHtml.getCssClass(widthType)).attr("data-ficheform-role", "textinput");
        int rows = formElement.getRows();
        hp
                .SECTION(formHandler.getEntryAttributes(formElement, "thesaurus-include")
                        .attr("data-ficheform-limit", "-1")
                        .attr(formElement.isWithExternalSource(), "data-ficheform-externalsource", "1")
                        .attr("data-subset-name", thesaurusName))
                .__(CommonFormHtml.printStandardLabel(hp, formElement, formHandler.getWorkingLang(), genId));
        if (rows == 1) {
            hp
                    .__(MOTCLE_INPUT_CELL, () -> {
                        hp
                                .INPUT_text(inputAttr.size(String.valueOf(defaultSize)).value(formElement.getValue()));
                    });
        } else {
            hp
                    .__(MULTIROWS_MOTCLE_INPUT_CELL, () -> {
                        hp
                                .TEXTAREA(inputAttr.cols(defaultSize).rows(rows))
                                .__escape(formElement.getValue(), true)
                                ._TEXTAREA();
                    });
        }
        hp
                ._SECTION();
        return true;
    }

    public static boolean printListThesaurusInclude(HtmlPrinter hp, ThesaurusIncludeElement.Choice formElement, FormHandler formHandler) {
        String name = formHandler.getPrefixedName(formElement);
        Lang lang = formHandler.getWorkingLang();
        String thesaurusName = formElement.getThesaurus().getSubsetName();
        String listType = formElement.geChoiceType();
        List<InputItem> inputItemList = new ArrayList<InputItem>();
        if ((formElement.isNoneAllowed()) && (!listType.equals(BdfServerConstants.INPUT_CHECK))) {
            inputItemList.add(new InputItem("", "---", formElement.isEmpty(), 1, false, false));
        } else if (listType.equals(BdfServerConstants.INPUT_SELECT)) {
            if ((!formElement.isNewIndexation()) && (formElement.isEmpty())) {
                inputItemList.add(new InputItem("", "---", true, 1, false, false));
            }
        }
        InputItem.populateInputItems(formElement, lang, inputItemList);
        HtmlAttributes entryAttr = formHandler.getEntryAttributes(formElement).attr("data-subset-name", thesaurusName);
        if (listType.equals(BdfServerConstants.INPUT_SELECT)) {
            HtmlAttributes selectAttr = hp.name(name);
            hp
                    .SECTION(entryAttr)
                    .__(CommonFormHtml.printStandardLabel(hp, formElement, lang, selectAttr.id()))
                    .__(FicheForm.STANDARD_CELL, () -> {
                        hp
                                .SELECT(selectAttr)
                                .__(InputItem.printOptions(hp, inputItemList))
                                ._SELECT();
                    })
                    ._SECTION();
        } else {
            HtmlAttributes attrModel = HA.name(name).attr("data-ficheform-grouped", "1");
            boolean isRadio = listType.equals(BdfServerConstants.INPUT_RADIO);
            if (isRadio) {
                attrModel.type(HtmlConstants.RADIO_TYPE);
            } else {
                attrModel.type(HtmlConstants.CHECKBOX_TYPE);
            }
            hp
                    .SECTION(entryAttr)
                    .__(CommonFormHtml.printStandardLabel(hp, formElement, lang, null))
                    .__(FicheForm.STANDARD_CELL, () -> {
                        if (!isRadio) {
                            hp
                                    .INPUT_hidden(name, "");
                        }
                        hp
                                .DIV("ficheform-Choices")
                                .__(InputItem.printInputList(hp, inputItemList, attrModel))
                                ._DIV();
                    })
                    ._SECTION();
        }
        return true;
    }

    public static boolean printNotEditableThesaurusInclude(HtmlPrinter hp, ThesaurusIncludeElement.NotEditable formElement, FormHandler formHandler) {
        String name = formHandler.getPrefixedName(formElement);
        StringBuilder valueBuffer = new StringBuilder();
        StringBuilder textBuffer = new StringBuilder();
        if (!formElement.isEmpty()) {
            boolean premier = true;
            int idalphaStyle = InputItem.getStyleValue(formElement.getIdalphaStyle());
            for (ThesaurusIncludeElement.Entry entry : formElement.getEntryList()) {
                Motcle motcle = entry.getMotcle();
                if (premier) {
                    premier = false;
                } else {
                    valueBuffer.append(";");
                    textBuffer.append(" ; ");
                }
                String idalpha = motcle.getIdalpha();
                if (idalpha == null) {
                    valueBuffer.append(motcle.getId());
                } else {
                    valueBuffer.append(idalpha);
                }
                textBuffer.append(InputItem.getText(motcle, formHandler.getWorkingLang(), idalphaStyle));
            }
        }
        hp
                .SECTION(formHandler.getEntryAttributes(formElement))
                .INPUT_hidden(name, valueBuffer.toString())
                .__(printNotEditableLabelSpans(hp, formElement.getLabel()))
                .__(FicheForm.STANDARD_CELL, () -> {
                    hp
                            .__escape(textBuffer.toString());
                })
                ._SECTION();
        return true;
    }

    public static boolean printFicheStyleThesaurusInclude(HtmlPrinter hp, ThesaurusIncludeElement.FicheStyle formElement, FormHandler formHandler) {
        Thesaurus thesaurus = formElement.getThesaurus();
        String name = formHandler.getPrefixedName(formElement);
        String genId = hp.generateId();
        hp
                .SECTION(formHandler.getEntryAttributes(formElement, "thesaurus-include")
                        .attr("data-ficheform-limit", "-1")
                        .attr(formElement.isWithExternalSource(), "data-ficheform-externalsource", "1")
                        .attr(!formElement.isWithExternalSource(), "data-ficheform-wanted", PiocheDomain.CODE_ID_WANTED)
                        .attr((!formElement.hasWeightFilter()), "data-ficheform-withweight", "1")
                        .attr("data-subset-name", thesaurus.getSubsetName())
                        .attr("data-ficheform-idalphastyle", getIdalphaStyle(formElement)))
                .__(CommonFormHtml.printStandardLabel(hp, formElement, formHandler.getWorkingLang(), genId))
                .__(printFicheStyleMotcleList(hp, formElement, name, formHandler.getUserLangContext()))
                .__(FicheForm.STANDARD_CELL, () -> {
                    hp
                            .DIV(HA.attr("data-ficheform-role", "searchcontainer").classes("ficheform-search-Container"))
                            .DIV(HA.attr("data-ficheform-role", "motcle-input").classes("ficheform-search-DirectInput"))
                            .INPUT_text(HA.name(name).id(genId)
                                    .attr("data-ficheform-role", "textinput")
                                    .classes("global-PlaceholderOnFocus ficheform-Full")
                                    .size("14")
                                    .attr("placeholder", hp.getLocalization("_ label.edition.directinput")))
                            ._DIV()
                            ._DIV();
                })
                ._SECTION();
        return true;
    }

    public static boolean printNotEditableLabelSpans(HtmlPrinter hp, String label) {
        hp
                .__breakLine()
                .SPAN("ficheform-standard-Label")
                .__escape(label)
                ._SPAN()
                .__breakLine()
                .SPAN("ficheform-standard-Colon")
                .__escape(':')
                ._SPAN()
                .__breakLine();
        return true;
    }

    private static boolean printFicheList(HtmlPrinter hp, CorpusIncludeElement formElement, String name, UserLangContext userLangContext, boolean withId) {
        List<CorpusIncludeElement.Entry> entryList = formElement.getEntryList();
        Lang workingLang = userLangContext.getWorkingLang();
        Locale formatLocale = userLangContext.getFormatLocale();
        hp
                .__(getEnumerationCell(entryList.isEmpty()), () -> {
                    if (hp.isWithJavascript()) {
                        hp.DIV(HA.attr("data-ficheform-role", "item-choices").classes("ficheform-Choices ficheform-Ordered"));
                        for (CorpusIncludeElement.Entry entry : entryList) {
                            int ficheId = -1;
                            if (withId) {
                                ficheId = entry.getFicheMeta().getId();
                            }
                            printItemChoice(hp, name, entry.getValue(), entry.getWeight(), CorpusMetadataUtils.getFicheTitle(entry.getFicheMeta(), workingLang, formatLocale), ficheId);
                        }
                        hp._DIV();
                    } else {
                        hp.DIV("ficheform-Choices");
                        for (CorpusIncludeElement.Entry entry : entryList) {
                            HtmlAttributes input = hp.name(name).value(entry.getValue()).size("5");
                            hp
                                    .DIV("ficheform-Choice")
                                    .INPUT_text(input)
                                    .__space()
                                    .LABEL_for(input.id())
                                    .__escape(CorpusMetadataUtils.getFicheTitle(entry.getFicheMeta(), workingLang, formatLocale))
                                    ._LABEL()
                                    ._DIV();
                        }
                        hp._DIV();
                    }
                });
        return true;
    }

    private static boolean printFicheTable(HtmlPrinter hp, CorpusIncludeElement.Table formElement, String name, UserLangContext userLangContext) {
        if (!hp.isWithJavascript()) {
            return printFicheList(hp, formElement, name, userLangContext, true);
        }
        CellConverter cellConverter = formElement.getCellConverter();
        List<CorpusIncludeElement.Entry> entryList = formElement.getEntryList();
        hp
                .__(getEnumerationCell(entryList.isEmpty()), () -> {
                    hp.TABLE(HA.classes("ficheform-fichetable-Table"));
                    hp.TBODY(HA.attr("data-ficheform-role", "fiche-rows").attr("data-ficheform-col-def-list", getColDefListString(formElement)).classes("ficheform-Ordered"));
                    for (CorpusIncludeElement.Entry entry : entryList) {
                        String ficheId = String.valueOf(entry.getFicheMeta().getId());
                        HtmlAttributes checkbox = hp.name(name).value(entry.getValue()).checked(true).attr("data-ficheform-role", "").classes("ficheform-fichetable-Checkbox");
                        hp.TR(HA.attr("data-ficheform-role", "fiche-row").attr("data-ficheform-item-id", ficheId));
                        hp
                                .TD(HA.attr("data-ficheform-role", "fiche-row-actioncell"))
                                .INPUT_checkbox(checkbox)
                                .SPAN(HA.attr("data-ficheform-role", "fiche-row-buttons"))
                                ._SPAN()
                                ._TD()
                                .TD("ficheform-fichetable-Number")
                                .__escape(ficheId)
                                ._TD();
                        Cell[] cellArray = cellConverter.toCellArray(entry.getFicheMeta());
                        for (Cell cell : cellArray) {
                            hp
                                    .TD(getCellClass(cell))
                                    .__(printValue(hp, cell))
                                    ._TD();
                        }
                        hp._TR();
                    }
                    hp._TBODY();
                    hp._TABLE();
                });
        return true;
    }

    private static String getCellClass(Cell cell) {
        ColDef colDef = cell.getColDef();
        Object paramValue = colDef.getParameterValue(CellSpace.FORMAT_KEY.toString());
        if ((paramValue != null) && (paramValue.equals("number"))) {
            return "ficheform-fichetable-Number";
        }
        return null;
    }

    private static HtmlWrapper getEnumerationCell(boolean empty) {
        if (empty) {
            return ENUMERATION_CELL_EMPTY;
        } else {
            return ENUMERATION_CELL;
        }
    }

    private static boolean printValue(HtmlPrinter hp, Cell cell) {
        Object value = cell.getValue();
        if (value == null) {
            return false;
        }
        String valueString = value.toString();
        HtmlTableWriter.printStringValue(hp, valueString);
        return true;
    }

    private static String getColDefListString(CorpusIncludeElement.Table formElement) {
        StringBuilder buf = new StringBuilder();
        for (ColDef colDef : formElement.getSubsetTable().getColDefList()) {
            if (buf.length() > 0) {
                buf.append(';');
            }
            buf.append(colDef.getColName());
            Object paramValue = colDef.getParameterValue(CellSpace.FORMAT_KEY.toString());
            if (paramValue != null) {
                buf.append('|');
                buf.append(paramValue);
            }
        }
        return buf.toString();
    }


    private static boolean printFicheStyleMotcleList(HtmlPrinter hp, ThesaurusIncludeElement.FicheStyle formElement, String name, UserLangContext userLangContext) {
        List<ThesaurusIncludeElement.Entry> entryList = formElement.getEntryList();
        int idalphaStyle = InputItem.getStyleValue(formElement.getIdalphaStyle());
        hp
                .__(getEnumerationCell(entryList.isEmpty()), () -> {
                    if (hp.isWithJavascript()) {
                        hp.DIV(HA.attr("data-ficheform-role", "item-choices").classes("ficheform-Choices ficheform-Ordered"));
                        for (ThesaurusIncludeElement.Entry entry : entryList) {
                            printItemChoice(hp, name, entry.getValue(), entry.getWeight(), geFicheStyleLabel(entry.getMotcle(), userLangContext, idalphaStyle), entry.getMotcle().getId());
                        }
                        hp._DIV();
                    } else {
                        hp.DIV("ficheform-Choices");
                        for (ThesaurusIncludeElement.Entry entry : entryList) {
                            HtmlAttributes input = hp.name(name).value(entry.getValue()).size("5");
                            hp
                                    .DIV("ficheform-Choice")
                                    .INPUT_text(input)
                                    .__space()
                                    .LABEL_for(input.id())
                                    .__escape(geFicheStyleLabel(entry.getMotcle(), userLangContext, idalphaStyle))
                                    ._LABEL()
                                    ._DIV();
                        }
                        hp._DIV();
                    }
                });
        return true;
    }

    private static boolean printItemChoice(HtmlPrinter hp, String name, String value, int weight, String label, int itemId) {
        HtmlAttributes container = HA.attr("data-ficheform-role", "item-choice").classes("ficheform-Choice");
        if (itemId > 0) {
            container.attr("data-ficheform-item-id", String.valueOf(itemId));
        }
        HtmlAttributes checkbox = hp.name(name).value(value).checked(true).attr("data-ficheform-role", "item-checkbox");
        hp
                .DIV(container)
                .INPUT_checkbox(checkbox)
                .LABEL_for(checkbox.id());
        if (weight > 0) {
            hp
                    .__space()
                    .SPAN(HA.attr("data-ficheform-role", "weight"));
            if (weight > 1) {
                hp
                        .__escape('<')
                        .__append(weight)
                        .__escape('>');
            }
            hp
                    ._SPAN();
        }
        hp
                .__space()
                .__escape(label)
                ._LABEL()
                ._DIV();
        return true;
    }


    private static String geFicheStyleLabel(Motcle motcle, UserLangContext userLangContext, int idalphaStyle) {
        String numberString = FichothequeUtils.getNumberPhrase(motcle, FichothequeConstants.FICHESTYLE_PHRASE, userLangContext.getWorkingLang(), userLangContext.getFormatLocale(), "");
        String title = InputItem.getText(motcle, userLangContext.getWorkingLang(), idalphaStyle);
        if (numberString.isEmpty()) {
            return title;
        } else {
            return numberString + " – " + title;
        }
    }

    private static String getIdalphaStyle(ThesaurusIncludeElement formElement) {
        Attribute attribute = formElement.getIdalphaStyle();
        if (attribute != null) {
            if (attribute.contains("brackets")) {
                return "brackets";
            } else if (attribute.contains("ignore")) {
                return "ignore";
            }
        }
        return null;
    }


}
