/* 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.FormEntry;
import fr.exemole.bdfserver.api.ficheform.include.AddendaEntry;
import fr.exemole.bdfserver.api.ficheform.include.AlbumEntry;
import fr.exemole.bdfserver.api.ficheform.include.CorpusEntry;
import fr.exemole.bdfserver.api.ficheform.include.LiageEntry;
import fr.exemole.bdfserver.api.ficheform.include.SubsetItemValue;
import fr.exemole.bdfserver.api.ficheform.include.ThesaurusEntry;
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.FicheMeta;
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 IncludeFormEntryHtml {

    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 IncludeFormEntryHtml() {
    }

    public static boolean print(HtmlPrinter hp, FormEntry.Include formEntry, FormHandler formHandler) {
        if (formEntry instanceof LiageEntry) {
            printLiage(hp, (LiageEntry) formEntry, formHandler);
        } else if (formEntry instanceof ThesaurusEntry.Text) {
            printTextThesaurus(hp, (ThesaurusEntry.Text) formEntry, formHandler);
        } else if (formEntry instanceof ThesaurusEntry.Choice) {
            printChoiceThesaurus(hp, (ThesaurusEntry.Choice) formEntry, formHandler);
        } else if (formEntry instanceof ThesaurusEntry.Hidden) {
            printHiddenThesaurus(hp, (ThesaurusEntry.Hidden) formEntry, formHandler);
        } else if (formEntry instanceof ThesaurusEntry.NotEditable) {
            printNotEditableThesaurus(hp, (ThesaurusEntry.NotEditable) formEntry, formHandler);
        } else if (formEntry instanceof ThesaurusEntry.FicheStyle) {
            printFicheStyleThesaurusEntry(hp, (ThesaurusEntry.FicheStyle) formEntry, formHandler);
        } else if (formEntry instanceof CorpusEntry.Check) {
            printCheckCorpus(hp, (CorpusEntry.Check) formEntry, formHandler);
        } else if (formEntry instanceof CorpusEntry.Table) {
            printTableCorpus(hp, (CorpusEntry.Table) formEntry, formHandler);
        } else if (formEntry instanceof AlbumEntry) {
            printAlbum(hp, (AlbumEntry) formEntry, formHandler, false);
        } else if (formEntry instanceof AddendaEntry) {
            printAddenda(hp, (AddendaEntry) formEntry, formHandler, false);
        } else {
            return false;
        }
        return true;
    }

    public static boolean printAddenda(HtmlPrinter hp, AddendaEntry formEntry, FormHandler formHandler, boolean withFileForm) {
        String name = formHandler.getPrefixedName(formEntry);
        String addendaName = formEntry.getAddenda().getSubsetName();
        List<Document> documentList = formEntry.getDocumentList();
        hp
                .SECTION(formHandler.getEntryAttributes(formEntry, "addenda-include").attr("data-subset-name", addendaName))
                .__(CommonFormHtml.printStandardLabel(hp, formEntry, 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 (formEntry.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 printAlbum(HtmlPrinter hp, AlbumEntry formEntry, FormHandler formHandler, boolean withUploadForm) {
        String name = formHandler.getPrefixedName(formEntry);
        String albumName = formEntry.getAlbum().getSubsetName();
        List<Illustration> illustrationList = formEntry.getIllustrationList();
        hp
                .SECTION(formHandler.getEntryAttributes(formEntry, "album-include")
                        .attr("data-subset-name", albumName))
                .__(CommonFormHtml.printStandardLabel(hp, formEntry, 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 printHiddenThesaurus(HtmlPrinter hp, ThesaurusEntry.Hidden formEntry, FormHandler formHandler) {
        String name = formHandler.getPrefixedName(formEntry);
        hp
                .INPUT_hidden(name, formEntry.getValue());
        return true;
    }

    public static boolean printLiage(HtmlPrinter hp, LiageEntry formEntry, FormHandler formHandler) {
        String name = formHandler.getPrefixedName(formEntry);
        String genId = hp.generateId();
        hp
                .SECTION(formHandler.getEntryAttributes(formEntry, "liage")
                        .attr("data-ficheform-limit", "-1")
                        .attr("data-ficheform-withweight", "1"))
                .__(CommonFormHtml.printStandardLabel(hp, formEntry, formHandler.getWorkingLang(), genId))
                .__(printFicheList(hp, formEntry.getValueList(), name, formHandler.getUserLangContext(), false))
                .__(printLiageDirectInput(hp, name, genId, formEntry))
                ._SECTION();
        return true;
    }

    public static boolean printCheckCorpus(HtmlPrinter hp, CorpusEntry.Check formEntry, FormHandler formHandler) {
        String name = formHandler.getPrefixedName(formEntry);
        String genId = hp.generateId();
        String corpusName = formEntry.getCorpus().getSubsetName();
        hp
                .SECTION(formHandler.getEntryAttributes(formEntry, "corpus-include")
                        .attr("data-ficheform-limit", "-1")
                        .attr((!formEntry.hasWeightFilter()), "data-ficheform-withweight", "1")
                        .attr("data-subset-name", corpusName)
                        .attr("data-ficheform-mode", "check"))
                .__(CommonFormHtml.printStandardLabel(hp, formEntry, formHandler.getWorkingLang(), genId))
                .__(printFicheList(hp, formEntry.getValueList(), name, formHandler.getUserLangContext(), true))
                .__(printCorpusDirectInput(hp, name, genId))
                ._SECTION();
        return true;
    }

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

    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, LiageEntry formEntry) {
        HtmlAttributes inputAttributes = HA.name(name).id(inputId).attr("data-ficheform-role", "textinput").classes("ficheform-Medium");
        int rows = formEntry.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 printTextThesaurus(HtmlPrinter hp, ThesaurusEntry.Text formEntry, FormHandler formHandler) {
        String name = formHandler.getPrefixedName(formEntry);
        String thesaurusName = formEntry.getThesaurus().getSubsetName();
        String widthType = formEntry.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 = formEntry.getRows();
        hp
                .SECTION(formHandler.getEntryAttributes(formEntry, "thesaurus-include")
                        .attr("data-ficheform-limit", "-1")
                        .attr(formEntry.isWithExternalSource(), "data-ficheform-externalsource", "1")
                        .attr("data-subset-name", thesaurusName))
                .__(CommonFormHtml.printStandardLabel(hp, formEntry, formHandler.getWorkingLang(), genId));
        if (rows == 1) {
            hp
                    .__(MOTCLE_INPUT_CELL, () -> {
                        hp
                                .INPUT_text(inputAttr.size(String.valueOf(defaultSize)).value(formEntry.getValue()));
                    });
        } else {
            hp
                    .__(MULTIROWS_MOTCLE_INPUT_CELL, () -> {
                        hp
                                .TEXTAREA(inputAttr.cols(defaultSize).rows(rows))
                                .__escape(formEntry.getValue(), true)
                                ._TEXTAREA();
                    });
        }
        hp
                ._SECTION();
        return true;
    }

    public static boolean printChoiceThesaurus(HtmlPrinter hp, ThesaurusEntry.Choice formEntry, FormHandler formHandler) {
        String name = formHandler.getPrefixedName(formEntry);
        Lang lang = formHandler.getWorkingLang();
        String thesaurusName = formEntry.getThesaurus().getSubsetName();
        String listType = formEntry.geChoiceType();
        List<InputItem> inputItemList = new ArrayList<InputItem>();
        if ((formEntry.isNoneAllowed()) && (!listType.equals(BdfServerConstants.INPUT_CHECK))) {
            inputItemList.add(new InputItem("", "---", formEntry.isEmpty(), 1, false, false));
        } else if (listType.equals(BdfServerConstants.INPUT_SELECT)) {
            if ((!formEntry.isNewIndexation()) && (formEntry.isEmpty())) {
                inputItemList.add(new InputItem("", "---", true, 1, false, false));
            }
        }
        InputItem.populateInputItems(formEntry, lang, inputItemList);
        HtmlAttributes entryAttr = formHandler.getEntryAttributes(formEntry).attr("data-subset-name", thesaurusName);
        if (listType.equals(BdfServerConstants.INPUT_SELECT)) {
            HtmlAttributes selectAttr = hp.name(name);
            hp
                    .SECTION(entryAttr)
                    .__(CommonFormHtml.printStandardLabel(hp, formEntry, 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, formEntry, 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 printNotEditableThesaurus(HtmlPrinter hp, ThesaurusEntry.NotEditable formEntry, FormHandler formHandler) {
        String name = formHandler.getPrefixedName(formEntry);
        StringBuilder valueBuffer = new StringBuilder();
        StringBuilder textBuffer = new StringBuilder();
        if (!formEntry.isEmpty()) {
            boolean premier = true;
            int idalphaStyle = InputItem.getStyleValue(formEntry.getIdalphaStyle());
            for (SubsetItemValue entry : formEntry.getValueList()) {
                Motcle motcle = (Motcle) entry.getSubsetItem();
                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(formEntry))
                .INPUT_hidden(name, valueBuffer.toString())
                .__(printNotEditableLabelSpans(hp, formEntry.getLabel()))
                .__(FicheForm.STANDARD_CELL, () -> {
                    hp
                            .__escape(textBuffer.toString());
                })
                ._SECTION();
        return true;
    }

    public static boolean printFicheStyleThesaurusEntry(HtmlPrinter hp, ThesaurusEntry.FicheStyle formEntry, FormHandler formHandler) {
        Thesaurus thesaurus = formEntry.getThesaurus();
        String name = formHandler.getPrefixedName(formEntry);
        String genId = hp.generateId();
        hp
                .SECTION(formHandler.getEntryAttributes(formEntry, "thesaurus-include")
                        .attr("data-ficheform-limit", "-1")
                        .attr(formEntry.isWithExternalSource(), "data-ficheform-externalsource", "1")
                        .attr(!formEntry.isWithExternalSource(), "data-ficheform-wanted", PiocheDomain.CODE_ID_WANTED)
                        .attr((!formEntry.hasWeightFilter()), "data-ficheform-withweight", "1")
                        .attr("data-subset-name", thesaurus.getSubsetName())
                        .attr("data-ficheform-idalphastyle", getIdalphaStyle(formEntry)))
                .__(CommonFormHtml.printStandardLabel(hp, formEntry, formHandler.getWorkingLang(), genId))
                .__(printFicheStyleMotcleList(hp, formEntry, 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, List<SubsetItemValue> valueList, String name, UserLangContext userLangContext, boolean withId) {
        Lang workingLang = userLangContext.getWorkingLang();
        Locale formatLocale = userLangContext.getFormatLocale();
        hp
                .__(getEnumerationCell(valueList.isEmpty()), () -> {
                    if (hp.isWithJavascript()) {
                        hp.DIV(HA.attr("data-ficheform-role", "item-choices").classes("ficheform-Choices ficheform-Ordered"));
                        for (SubsetItemValue subsetItemValue : valueList) {
                            String label = CorpusMetadataUtils.getFicheTitle((FicheMeta) subsetItemValue.getSubsetItem(), workingLang, formatLocale);
                            printItemChoice(hp, name, subsetItemValue, label, withId);
                        }
                        hp._DIV();
                    } else {
                        hp.DIV("ficheform-Choices");
                        for (SubsetItemValue subsetItemValue : valueList) {
                            String label = CorpusMetadataUtils.getFicheTitle((FicheMeta) subsetItemValue.getSubsetItem(), workingLang, formatLocale);
                            HtmlAttributes input = hp.name(name).value(subsetItemValue.getValue()).size("5");
                            hp
                                    .DIV("ficheform-Choice")
                                    .INPUT_text(input)
                                    .__space()
                                    .LABEL_for(input.id())
                                    .__escape(label)
                                    ._LABEL()
                                    ._DIV();
                        }
                        hp._DIV();
                    }
                });
        return true;
    }

    private static boolean printFicheTable(HtmlPrinter hp, CorpusEntry.Table formEntry, String name, UserLangContext userLangContext) {
        if (!hp.isWithJavascript()) {
            return printFicheList(hp, formEntry.getValueList(), name, userLangContext, true);
        }
        CellConverter cellConverter = formEntry.getCellConverter();
        List<SubsetItemValue> valueList = formEntry.getValueList();
        hp
                .__(getEnumerationCell(valueList.isEmpty()), () -> {
                    hp.TABLE(HA.classes("ficheform-fichetable-Table"));
                    hp.TBODY(HA.attr("data-ficheform-role", "fiche-rows").attr("data-ficheform-col-def-list", getColDefListString(formEntry)).classes("ficheform-Ordered"));
                    for (SubsetItemValue subsetItemValue : valueList) {
                        String ficheId = String.valueOf(subsetItemValue.getSubsetItem().getId());
                        HtmlAttributes checkbox = hp.name(name).value(subsetItemValue.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(subsetItemValue.getSubsetItem());
                        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(CorpusEntry.Table formEntry) {
        StringBuilder buf = new StringBuilder();
        for (ColDef colDef : formEntry.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, ThesaurusEntry.FicheStyle formEntry, String name, UserLangContext userLangContext) {
        List<SubsetItemValue> valueList = formEntry.getValueList();
        int idalphaStyle = InputItem.getStyleValue(formEntry.getIdalphaStyle());
        hp
                .__(getEnumerationCell(valueList.isEmpty()), () -> {
                    if (hp.isWithJavascript()) {
                        hp.DIV(HA.attr("data-ficheform-role", "item-choices").classes("ficheform-Choices ficheform-Ordered"));
                        for (SubsetItemValue subsetItemValue : valueList) {
                            String label = geFicheStyleLabel((Motcle) subsetItemValue.getSubsetItem(), userLangContext, idalphaStyle);
                            printItemChoice(hp, name, subsetItemValue, label, true);
                        }
                        hp._DIV();
                    } else {
                        hp.DIV("ficheform-Choices");
                        for (SubsetItemValue subsetItemValue : valueList) {
                            String label = geFicheStyleLabel((Motcle) subsetItemValue.getSubsetItem(), userLangContext, idalphaStyle);
                            HtmlAttributes input = hp.name(name).value(subsetItemValue.getValue()).size("5");
                            hp
                                    .DIV("ficheform-Choice")
                                    .INPUT_text(input)
                                    .__space()
                                    .LABEL_for(input.id())
                                    .__escape(label)
                                    ._LABEL()
                                    ._DIV();
                        }
                        hp._DIV();
                    }
                });
        return true;
    }

    private static boolean printItemChoice(HtmlPrinter hp, String name, SubsetItemValue subsetItemValue, String label, boolean withId) {

        HtmlAttributes container = HA.attr("data-ficheform-role", "item-choice").classes("ficheform-Choice");
        if (withId) {
            container.attr("data-ficheform-item-id", String.valueOf(subsetItemValue.getSubsetItem().getId()));
        }
        HtmlAttributes checkbox = hp.name(name).value(subsetItemValue.getValue()).checked(true).attr("data-ficheform-role", "item-checkbox");
        hp
                .DIV(container)
                .INPUT_checkbox(checkbox)
                .LABEL_for(checkbox.id());
        int weight = subsetItemValue.getWeight();
        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(ThesaurusEntry formEntry) {
        Attribute attribute = formEntry.getIdalphaStyle();
        if (attribute != null) {
            if (attribute.contains("brackets")) {
                return "brackets";
            } else if (attribute.contains("ignore")) {
                return "ignore";
            }
        }
        return null;
    }


}
