/* BdfServer_HtmlProducers - Copyright (c) 2012-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.htmlproducers.thesaurus;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.BdfServerConstants;
import fr.exemole.bdfserver.api.managers.UiManager;
import fr.exemole.bdfserver.api.subsettree.SubsetTree;
import fr.exemole.bdfserver.api.ui.SubsetIncludeUi;
import fr.exemole.bdfserver.api.ui.UiComponent;
import fr.exemole.bdfserver.api.ui.UiComponents;
import fr.exemole.bdfserver.commands.thesaurus.ChildrenReorderCommand;
import fr.exemole.bdfserver.commands.thesaurus.IdalphaChangeCommand;
import fr.exemole.bdfserver.commands.thesaurus.IdalphaSortCommand;
import fr.exemole.bdfserver.commands.thesaurus.LabelChangeCommand;
import fr.exemole.bdfserver.commands.thesaurus.MotcleAttributeChangeCommand;
import fr.exemole.bdfserver.commands.thesaurus.MotcleCreationCommand;
import fr.exemole.bdfserver.commands.thesaurus.MotcleIndexationCommand;
import fr.exemole.bdfserver.commands.thesaurus.MotcleMergeCommand;
import fr.exemole.bdfserver.commands.thesaurus.MotcleMoveCommand;
import fr.exemole.bdfserver.commands.thesaurus.MotcleRemoveCommand;
import fr.exemole.bdfserver.commands.thesaurus.MotcleStatusCommand;
import fr.exemole.bdfserver.commands.thesaurus.ParentChangeCommand;
import fr.exemole.bdfserver.commands.thesaurus.ThesaurusAttributeChangeCommand;
import fr.exemole.bdfserver.commands.thesaurus.ThesaurusCleaningCommand;
import fr.exemole.bdfserver.commands.thesaurus.ThesaurusCloneCommand;
import fr.exemole.bdfserver.commands.thesaurus.ThesaurusCreationCommand;
import fr.exemole.bdfserver.commands.thesaurus.ThesaurusLangListCommand;
import fr.exemole.bdfserver.commands.thesaurus.ThesaurusPhrasesCommand;
import fr.exemole.bdfserver.commands.thesaurus.ThesaurusRemoveCommand;
import fr.exemole.bdfserver.html.BdfHtmlUtils;
import fr.exemole.bdfserver.html.consumers.AttributesText;
import fr.exemole.bdfserver.html.consumers.Common;
import fr.exemole.bdfserver.html.consumers.Grid;
import fr.exemole.bdfserver.html.consumers.LangRows;
import fr.exemole.bdfserver.html.consumers.MetadataPhrases;
import fr.exemole.bdfserver.html.consumers.SubsetTitle;
import fr.exemole.bdfserver.html.consumers.SubsetTreeOptions;
import fr.exemole.bdfserver.html.consumers.attributes.Appelant;
import fr.exemole.bdfserver.html.consumers.attributes.Deploy;
import fr.exemole.bdfserver.html.consumers.attributes.InputPattern;
import fr.exemole.bdfserver.html.consumers.commandbox.Flag;
import static fr.exemole.bdfserver.htmlproducers.CommandBoxUtils.insert;
import fr.exemole.bdfserver.tools.subsettree.TreeUtils;
import fr.exemole.bdfserver.tools.ui.MetadataPhraseDefCatalog;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import net.fichotheque.Fichotheque;
import net.fichotheque.FichothequeConstants;
import net.fichotheque.SubsetItem;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.FicheMeta;
import net.fichotheque.junction.Liaison;
import net.fichotheque.permission.PermissionSummary;
import net.fichotheque.syntax.FormSyntax;
import net.fichotheque.thesaurus.Motcle;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.thesaurus.metadata.ThesaurusMetadata;
import net.fichotheque.utils.CorpusMetadataUtils;
import net.fichotheque.utils.FichothequeUtils;
import net.fichotheque.utils.JunctionUtils;
import net.mapeadores.util.annotation.Nullable;
import net.mapeadores.util.exceptions.SwitchException;
import net.mapeadores.util.html.CommandBox;
import net.mapeadores.util.html.HtmlAttributes;
import net.mapeadores.util.html.HtmlPrinter;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.Langs;
import net.mapeadores.util.localisation.LangsUtils;
import net.mapeadores.util.text.Label;
import net.mapeadores.util.text.Labels;


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


    private ThesaurusCommandBoxUtils() {
    }

    public static boolean printThesaurusCreationBox(HtmlPrinter hp, CommandBox commandBox, BdfServer bdfServer) {
        commandBox = commandBox.derive(ThesaurusCreationCommand.COMMANDNAME, ThesaurusCreationCommand.COMMANDKEY)
                .actionCssClass("action-New")
                .__(Flag.UPDATE_COLLECTIONS)
                .submitLocKey("_ submit.thesaurus.thesauruscreation");
        hp
                .__start(commandBox)
                .__(Grid.START)
                .__(Grid.textInputRow("_ label.thesaurus.newthesaurusname", hp.name(ThesaurusCreationCommand.NEWTHESAURUS_PARAMNAME).size("30").populate(InputPattern.TECHNICAL_STRICT).required(true)))
                .__(Grid.choiceSetRow("_ label.thesaurus.thesaurustype",
                        () -> {
                            hp
                                    .__(printRadioType(hp, ThesaurusMetadata.MULTI_TYPE, true))
                                    .__(printRadioType(hp, ThesaurusMetadata.IDALPHA_TYPE, false))
                                    .__(printRadioType(hp, ThesaurusMetadata.BABELIEN_TYPE, false));
                        }))
                .__(Grid.END)
                .__end(commandBox);
        return true;
    }

    public static boolean printThesaurusPhrasesBox(HtmlPrinter hp, CommandBox commandBox, Thesaurus thesaurus, BdfServer bdfServer) {
        Langs langs = bdfServer.getLangConfiguration().getWorkingLangs();
        Langs authorizedLangs = bdfServer.getThesaurusLangChecker().getAuthorizedLangs(thesaurus);
        if (authorizedLangs != null) {
            langs = LangsUtils.merge(langs, authorizedLangs);
        }
        ThesaurusMetadata thesaurusMetadata = thesaurus.getThesaurusMetadata();
        MetadataPhrases metadataPhrases = MetadataPhrases.init(thesaurusMetadata, langs, "_ label.thesaurus.title");
        if (isFicheStyleUsed(thesaurus, bdfServer)) {
            metadataPhrases.addDef(MetadataPhraseDefCatalog.getMetadataPhraseDef(FichothequeConstants.FICHESTYLE_PHRASE));
        }
        metadataPhrases
                .populateFromAttributes(thesaurus)
                .addExtensionPhraseDefList(bdfServer);
        commandBox = commandBox.derive(ThesaurusPhrasesCommand.COMMANDNAME, ThesaurusPhrasesCommand.COMMANDKEY)
                .__(insert(thesaurus))
                .actionCssClass("action-Labels")
                .submitLocKey("_ submit.thesaurus.thesaurusphrases");
        hp
                .__start(commandBox)
                .__(metadataPhrases)
                .__end(commandBox);
        return true;
    }

    public static boolean printThesaurusLangListBox(HtmlPrinter hp, CommandBox commandBox, Thesaurus thesaurus, BdfServer bdfServer) {
        if (thesaurus.isBabelienType()) {
            return false;
        }
        Langs langs = bdfServer.getThesaurusLangChecker().getAuthorizedLangs(thesaurus);
        commandBox = commandBox.derive(ThesaurusLangListCommand.COMMANDNAME, ThesaurusLangListCommand.COMMANDKEY)
                .__(insert(thesaurus))
                .submitLocKey("_ submit.thesaurus.langlist");
        hp
                .__start(commandBox)
                .P("global-SubTitle")
                .__localize(ThesaurusHtmlUtils.getThesaurusTypeMessageKey(thesaurus.getThesaurusMetadata().getThesaurusType()))
                ._P()
                .__(Grid.START)
                .__(Grid.textInputRow("_ label.thesaurus.langlist", hp.name(ThesaurusLangListCommand.LANGLIST_PARAMNAME).value(langs.toString(";")).size("15")))
                .__(Grid.END)
                .__end(commandBox);
        return true;
    }

    public static boolean printThesaurusRemoveBox(HtmlPrinter hp, CommandBox commandBox, Thesaurus thesaurus) {
        commandBox = commandBox.derive(ThesaurusRemoveCommand.COMMANDNAME, ThesaurusRemoveCommand.COMMANDKEY)
                .__(insert(thesaurus))
                .actionCssClass("action-Delete")
                .__(Flag.UPDATE_COLLECTIONS)
                .submitLocKey("_ submit.thesaurus.thesaurusremove");
        hp
                .__start(commandBox)
                .__(Common.REMOVE_CONFIRM_CHECK)
                .__end(commandBox);
        return true;
    }

    public static boolean printThesaurusCleaningBox(HtmlPrinter hp, CommandBox commandBox, Thesaurus thesaurus, Lang workingLang) {
        commandBox = commandBox.derive(ThesaurusCleaningCommand.COMMANDNAME, ThesaurusCleaningCommand.COMMANDKEY)
                .__(insert(thesaurus))
                .submitLocKey("_ submit.thesaurus.thesauruscleaning");
        hp
                .__start(commandBox)
                .P()
                .__localize("_ warning.thesaurus.cleaningconfirmation", FichothequeUtils.getTitle(thesaurus, workingLang))
                ._P()
                .__(Common.CLEANING_CONFIRM_CHECK)
                .__end(commandBox);
        return true;
    }

    public static boolean printThesaurusCloneBox(HtmlPrinter hp, CommandBox commandBox, Thesaurus thesaurus, Lang lang) {
        List<Corpus> satelliteCorpusList = thesaurus.getSatelliteCorpusList();
        commandBox = commandBox.derive(ThesaurusCloneCommand.COMMANDNAME, ThesaurusCloneCommand.COMMANDKEY)
                .__(insert(thesaurus))
                .actionCssClass("action-Duplicate")
                .submitLocKey("_ submit.thesaurus.thesaurusclone");
        hp
                .__start(commandBox)
                .__(Grid.START)
                .__(Grid.textInputRow("_ label.thesaurus.newthesaurusname", hp.name(ThesaurusCloneCommand.NEWTHESAURUS_PARAMNAME).size("30").populate(InputPattern.TECHNICAL_STRICT).required(true)))
                .__(Grid.checkboxRow("_ label.thesaurus.reinitid", hp.name(ThesaurusCloneCommand.REINITID_PARAMNAME).value("1").checked(false)))
                .__(Grid.checkboxRow("_ label.thesaurus.junctioncopy", hp.name(ThesaurusCloneCommand.COPYJUNCTIONS_PARAMNAME).value("1").checked(false)));
        if (!satelliteCorpusList.isEmpty()) {
            String satelliteDetailId = hp.generateId();
            hp
                    .__(Grid.checkboxRow("_ label.thesaurus.clonesatellite", hp.name(ThesaurusCloneCommand.CLONESATELLITE_PARAMNAME).value("1").checked(false).populate(Deploy.checkbox(satelliteDetailId)),
                            () -> {
                                hp
                                        .DIV(Grid.detailPanelTable().id(satelliteDetailId).addClass("hidden"));
                                for (Corpus corpus : satelliteCorpusList) {
                                    printSatelliteCorpusCheckBox(hp, corpus, lang);
                                }
                                hp
                                        ._DIV();
                            }));
        }
        hp
                .__(Grid.END)
                .__end(commandBox);
        return true;
    }

    private static boolean printSatelliteCorpusCheckBox(HtmlPrinter hp, Corpus corpus, Lang lang) {
        String corpusName = corpus.getSubsetName();
        String corpusDetailId = hp.generateId();
        hp
                .__(Grid.checkboxRow(SubsetTitle.init(corpus, lang).subsetName(true), hp.name(ThesaurusCloneCommand.SATELLITECORPUS_PARAMNAME).value(corpusName).checked(false).populate(Deploy.checkbox(corpusDetailId)),
                        () -> {
                            hp
                                    .DIV(Grid.detailPanelTable().id(corpusDetailId).addClass("hidden"))
                                    .__(Grid.textInputRow("_ label.corpus.newcorpusname", hp.name(ThesaurusCloneCommand.NEWCORPUS_PREFIX + corpusName).size("30").populate(InputPattern.TECHNICAL_STRICT)))
                                    .__(Grid.checkboxRow("_ label.corpus.clonefiches", hp.name(ThesaurusCloneCommand.CLONEFICHES_PREFIX + corpusName).value("1").checked(false)))
                                    ._DIV();

                        }));
        return true;
    }

    public static boolean printChildrenReorderBox(HtmlPrinter hp, CommandBox commandBox, Thesaurus thesaurus, Motcle motcle) {
        boolean isIdalpha = thesaurus.isIdalphaType();
        List<Motcle> children = (motcle != null) ? motcle.getChildList() : thesaurus.getFirstLevelList();
        Object insertObject;
        if (motcle != null) {
            insertObject = motcle;
        } else {
            insertObject = thesaurus;
        }
        commandBox = commandBox.derive(ChildrenReorderCommand.COMMANDNAME, ChildrenReorderCommand.COMMANDKEY)
                .__(insert(insertObject))
                .submitLocKey("_ submit.thesaurus.childrenreorder");
        hp
                .__start(commandBox)
                .__(Grid.START)
                .__(Grid.textAreaBlockRow("_ label.thesaurus.children", hp.name(ChildrenReorderCommand.CHILDREN_PARAMNAME).classes("command-LargeInput").cols(40).rows(20),
                        () -> {
                            int count = children.size();
                            for (int i = 0; i < count; i++) {
                                if (i > 0) {
                                    hp
                                            .__newLine();
                                }
                                Motcle child = children.get(i);
                                if (isIdalpha) {
                                    hp
                                            .__escape(child.getIdalpha());
                                } else {
                                    hp
                                            .__append(child.getId());
                                }
                            }
                        }))
                .__(Grid.END)
                .__end(commandBox);
        return true;
    }

    public static boolean printIdalphaSortBox(HtmlPrinter hp, CommandBox commandBox, Thesaurus thesaurus, Motcle motcle) {
        Object insertObject;
        if (motcle != null) {
            insertObject = motcle;
        } else {
            insertObject = thesaurus;
        }
        commandBox = commandBox.derive(IdalphaSortCommand.COMMANDNAME, IdalphaSortCommand.COMMANDKEY)
                .__(insert(insertObject))
                .submitLocKey("_ submit.thesaurus.idalphasort");
        hp
                .__start(commandBox)
                .__(Grid.START)
                .__(Grid.checkboxRow("_ label.thesaurus.sort_recursive", hp.name(IdalphaSortCommand.RECURSIVE_PARAMNAME).value("1")))
                .__(Grid.checkboxRow("_ label.thesaurus.sort_descending", hp.name(IdalphaSortCommand.DESCENDING_PARAMNAME).value("1")))
                .__(Grid.checkboxRow("_ label.thesaurus.sort_ignorecase", hp.name(IdalphaSortCommand.IGNORECASE_PARAMNAME).value("1")))
                .__(Grid.checkboxRow("_ label.thesaurus.sort_ignorepunctuation", hp.name(IdalphaSortCommand.IGNOREPUNCTUATION_PARAMNAME).value("1")))
                .__(Grid.END)
                .__end(commandBox);
        return true;
    }

    public static boolean printMotcleCreationBox(HtmlPrinter hp, CommandBox commandBox, Thesaurus thesaurus, Motcle parentMotcle, BdfServer bdfServer, Lang lang) {
        commandBox = commandBox.derive(MotcleCreationCommand.COMMANDNAME, MotcleCreationCommand.COMMANDKEY)
                .__(insert(thesaurus))
                .actionCssClass("action-New")
                .submitLocKey("_ submit.thesaurus.motclecreation");
        if (parentMotcle != null) {
            commandBox.hidden(MotcleCreationCommand.PARENT_PARAMNAME, String.valueOf(parentMotcle.getId()));
        }
        hp.__start(commandBox);
        if (thesaurus.isIdalphaType()) {
            hp
                    .__(Grid.START)
                    .__(Grid.textInputRow("_ label.thesaurus.newidalpha", hp.name(MotcleCreationCommand.NEWIDALPHA_PARAMNAME).size("30").populate(InputPattern.IDALPHA).required(true)))
                    .__(printParentMotcle(hp, parentMotcle, lang))
                    .__(Grid.END);
        } else if (thesaurus.isBabelienType()) {
            hp
                    .__(Grid.START)
                    .__(printParentMotcle(hp, parentMotcle, lang))
                    .__(Grid.textAreaBlockRow("_ label.thesaurus.label_one", hp.name(MotcleCreationCommand.BABELIEN_NEWLABEL_PARAMNAME).cols(60).rows(3)))
                    .__(Grid.textInputRow("_ label.thesaurus.babelienlang", hp.name(MotcleCreationCommand.BABELIEN_NEWLANG_PARAMNAME).value(lang.toString()).size("3").populate(InputPattern.LANG).required(true)))
                    .__(Grid.END);
        } else if (parentMotcle != null) {
            hp
                    .__(Grid.START)
                    .__(printParentMotcle(hp, parentMotcle, lang))
                    .__(Grid.END);
        }
        if (!thesaurus.isBabelienType()) {
            Langs langs = bdfServer.getThesaurusLangChecker().getAuthorizedLangs(thesaurus);
            String messageKey = (langs.size() == 1) ? "_ label.thesaurus.label_one" : "_ label.thesaurus.label_many";
            hp
                    .DL("global-DL")
                    .__(printMotcleLabelTable(hp, null, MotcleCreationCommand.NEWLABEL_PARAMPREFIX, langs, messageKey))
                    ._DL();
        }
        hp
                .__end(commandBox);
        return true;
    }

    private static boolean printParentMotcle(HtmlPrinter hp, Motcle parentMotcle, Lang lang) {
        if (parentMotcle == null) {
            return false;
        }
        hp
                .__(Grid.START_ROW)
                .__(Grid.labelCells("_ label.thesaurus.parent"))
                .__(Grid.START_INPUTCELL)
                .__(BdfHtmlUtils.printMotcleTitle(hp, parentMotcle, lang))
                .__(Grid.END_INPUTCELL)
                .__(Grid.END_ROW);
        return true;
    }

    public static boolean printIdalphaChangeBox(HtmlPrinter hp, CommandBox commandBox, Motcle motcle) {
        commandBox = commandBox.derive(IdalphaChangeCommand.COMMANDNAME, IdalphaChangeCommand.COMMANDKEY)
                .__(insert(motcle))
                .submitLocKey("_ submit.thesaurus.idalphachange");
        hp
                .__start(commandBox)
                .__(Grid.START)
                .__(Grid.textInputRow("_ label.thesaurus.idalpha", hp.name(IdalphaChangeCommand.NEWIDALPHA_PARAMNAME).value(motcle.getIdalpha()).size("30").populate(InputPattern.IDALPHA).required(true)))
                .__(Grid.END)
                .__end(commandBox);
        return true;
    }

    public static boolean printParentChangeBox(HtmlPrinter hp, CommandBox commandBox, Motcle motcle, Lang lang) {
        boolean withIdalpha = motcle.getThesaurus().isIdalphaType();
        String messageKey = (withIdalpha) ? "_ label.thesaurus.parent_idalpha" : "_ label.thesaurus.parent_id";
        String parentValue = "";
        Motcle parentMotcle = motcle.getParent();
        if (parentMotcle != null) {
            if (withIdalpha) {
                parentValue = parentMotcle.getIdalpha();
            } else {
                parentValue = String.valueOf(parentMotcle.getId());
            }
        }
        commandBox = commandBox.derive(ParentChangeCommand.COMMANDNAME, ParentChangeCommand.COMMANDKEY)
                .__(insert(motcle))
                .submitLocKey("_ submit.thesaurus.parentchange");
        hp
                .__start(commandBox)
                .__(Grid.START)
                .__(printParentMotcle(hp, parentMotcle, lang))
                .__(Grid.textInputRow(messageKey, hp.name(ParentChangeCommand.NEWPARENT_PARAMNAME).value(parentValue).size("30")))
                .__(Grid.END)
                .__end(commandBox);
        return true;
    }

    public static boolean printLabelChangeBox(HtmlPrinter hp, CommandBox commandBox, Motcle motcle, BdfServer bdfServer) {
        Thesaurus thesaurus = motcle.getThesaurus();
        boolean isBabelien = thesaurus.isBabelienType();
        boolean manyLang = false;
        Langs langs;
        if (!isBabelien) {
            langs = bdfServer.getThesaurusLangChecker().getAuthorizedLangs(thesaurus);
            manyLang = (langs.size() > 1);
        } else {
            langs = null;
        }
        commandBox = commandBox.derive(LabelChangeCommand.COMMANDNAME, LabelChangeCommand.COMMANDKEY)
                .__(insert(motcle))
                .submitLocKey((manyLang) ? "_ submit.thesaurus.labelchange_many" : "_ submit.thesaurus.labelchange_one");
        hp
                .__start(commandBox);
        if (isBabelien) {
            Label label = motcle.getBabelienLabel();
            hp
                    .__(Grid.START)
                    .__(Grid.textAreaBlockRow("_ label.thesaurus.label_one", hp.name(LabelChangeCommand.BABELIEN_LABEL_PARAMNAME).cols(60).rows(3),
                            () -> {
                                hp
                                        .__escape(FormSyntax.escapeString(label.getLabelString()));
                            }))
                    .__(Grid.textInputRow("_ label.thesaurus.babelienlang", hp.name(LabelChangeCommand.BABELIEN_LANG_PARAMNAME).value(label.getLang().toString()).size("3")))
                    .__(Grid.END);
        } else {
            String messageKey = (manyLang) ? "_ label.thesaurus.label_many" : "_ label.thesaurus.label_one";
            hp
                    .DL("global-DL")
                    .__(printMotcleLabelTable(hp, motcle, LabelChangeCommand.LABEL_PARAMPREFIX, langs, messageKey))
                    ._DL();
        }
        hp
                .__end(commandBox);
        return true;
    }

    public static boolean printThesaurusAttributeChangeBox(HtmlPrinter hp, CommandBox commandBox, Thesaurus thesaurus) {
        commandBox = commandBox.derive(ThesaurusAttributeChangeCommand.COMMANDNAME, ThesaurusAttributeChangeCommand.COMMANDKEY)
                .__(insert(thesaurus))
                .actionCssClass("action-Attributes")
                .submitLocKey("_ submit.global.attributechange");
        hp
                .__start(commandBox)
                .__(Grid.START)
                .__(Grid.textAreaBlockRow("_ label.global.attributes", hp.name(ThesaurusAttributeChangeCommand.ATTRIBUTES_PARAMNAME).rows(8).cols(75).attr("data-codemirror-mode", "attributes"),
                        new AttributesText(thesaurus.getThesaurusMetadata().getAttributes())))
                .__(Grid.END)
                .__end(commandBox);
        return true;
    }

    public static boolean printMotcleStatusBox(HtmlPrinter hp, CommandBox commandBox, Motcle motcle) {
        String status = motcle.getStatus();
        commandBox = commandBox.derive(MotcleStatusCommand.COMMANDNAME, MotcleStatusCommand.COMMANDKEY)
                .__(insert(motcle))
                .submitLocKey("_ submit.thesaurus.motclestatus");
        hp
                .__start(commandBox)
                .__(Grid.START)
                .__(printStatusRow(hp, FichothequeConstants.ACTIVE_STATUS, status))
                .__(printStatusRow(hp, FichothequeConstants.GROUP_STATUS, status))
                .__(printStatusRow(hp, FichothequeConstants.OBSOLETE_STATUS, status))
                .__(Grid.END)
                .__end(commandBox);
        return true;
    }

    public static boolean printMotcleAttributeChangeBox(HtmlPrinter hp, CommandBox commandBox, Motcle motcle) {
        commandBox = commandBox.derive(MotcleAttributeChangeCommand.COMMANDNAME, MotcleAttributeChangeCommand.COMMANDKEY)
                .__(insert(motcle))
                .actionCssClass("action-Attributes")
                .submitLocKey("_ submit.global.attributechange");
        hp
                .__start(commandBox)
                .__(Grid.START)
                .__(Grid.textAreaBlockRow("_ label.global.attributes", hp.name(MotcleAttributeChangeCommand.ATTRIBUTES_PARAMNAME).rows(8).cols(75).attr("data-codemirror-mode", "attributes"),
                        new AttributesText(motcle.getAttributes())
                ))
                .__(Grid.END)
                .__end(commandBox);
        return true;
    }

    public static boolean printMotcleRemoveBox(HtmlPrinter hp, CommandBox commandBox, Motcle motcle, Lang workingLang, Locale formatLocale) {
        List<FicheMeta> satelliteList = new ArrayList<FicheMeta>();
        int motcleid = motcle.getId();
        for (Corpus satelliteCorpus : motcle.getThesaurus().getSatelliteCorpusList()) {
            FicheMeta ficheMeta = satelliteCorpus.getFicheMetaById(motcleid);
            if (ficheMeta != null) {
                satelliteList.add(ficheMeta);
            }
        }
        commandBox = commandBox.derive(MotcleRemoveCommand.COMMANDNAME, MotcleRemoveCommand.COMMANDKEY)
                .__(insert(motcle))
                .actionCssClass("action-Delete")
                .submitLocKey("_ submit.thesaurus.motcleremove");
        hp
                .__start(commandBox)
                .__if(!satelliteList.isEmpty(), () -> {
                    hp
                            .P("global-Warning")
                            .__localize("_ warning.corpus.satelliteremove")
                            ._P();
                    hp
                            .UL();
                    for (FicheMeta satelliteFicheMeta : satelliteList) {
                        hp
                                .LI()
                                .__escape(CorpusMetadataUtils.getFicheTitle(satelliteFicheMeta, workingLang, formatLocale))
                                ._LI();
                    }
                    hp
                            ._UL();
                })
                .__(Common.REMOVE_CONFIRM_CHECK)
                .__end(commandBox);
        return true;
    }

    public static boolean printMotcleIndexationBox(HtmlPrinter hp, CommandBox commandBox, Motcle motcle, Lang workingLang, PermissionSummary permissionSummary) {
        Thesaurus thesaurus = motcle.getThesaurus();
        Fichotheque fichotheque = thesaurus.getFichotheque();
        commandBox = commandBox.derive(MotcleIndexationCommand.COMMANDNAME, MotcleIndexationCommand.COMMANDKEY)
                .__(insert(motcle))
                .submitLocKey("_ submit.thesaurus.motcleindexation");
        hp
                .__start(commandBox);
        for (Corpus corpus : fichotheque.getCorpusList()) {
            if (!permissionSummary.hasAccess(corpus)) {
                continue;
            }
            hp
                    .H3()
                    .__escape(FichothequeUtils.getTitle(corpus, workingLang))
                    ._H3();
            hp
                    .TEXTAREA(hp.name(corpus.getSubsetKeyString()).cols(60).rows(3).classes("command-LargeInput"));
            Collection<Liaison> liaisons = JunctionUtils.sortByWeight(fichotheque.getJunctions(motcle, corpus), "");
            for (Liaison liaison : liaisons) {
                SubsetItem subsetItem = liaison.getSubsetItem();
                hp
                        .__append(subsetItem.getId());
                int weight = liaison.getTie().getWeight();
                if (weight > 1) {
                    hp
                            .__space()
                            .__escape('<')
                            .__append(weight)
                            .__escape('>');
                }
                hp
                        .__escape("; ");
            }
            hp.
                    _TEXTAREA();
        }
        hp
                .__end(commandBox);
        return true;
    }

    public static boolean printMotcleMoveBox(HtmlPrinter hp, CommandBox commandBox, Motcle motcle, BdfServer bdfServer, Lang workingLang, SubsetTree adminSubsetTree, SubsetKey selectedSubsetKey) {
        SubsetKey checkedSelectedSubsetKey = testSubsetKey(adminSubsetTree, selectedSubsetKey);
        if (checkedSelectedSubsetKey == null) {
            return false;
        }
        Thesaurus thesaurus = motcle.getThesaurus();
        commandBox = commandBox.derive(MotcleMoveCommand.COMMANDNAME, MotcleMoveCommand.COMMANDKEY)
                .__(insert(motcle))
                .actionCssClass("action-Move")
                .submitLocKey("_ submit.thesaurus.motclemove");
        hp
                .__start(commandBox)
                .__(Grid.START)
                .__(Grid.selectRow("_ label.thesaurus.destinationthesaurus", hp.name(MotcleMoveCommand.DESTINATIONTHESAURUS_PARAMNAME),
                        SubsetTreeOptions.init(adminSubsetTree, bdfServer, workingLang)
                                .onlyNames(true)
                                .withKeys(true)
                                .disabledSet(Collections.singleton(thesaurus.getSubsetKey()))
                                .selectedSubsetKey(checkedSelectedSubsetKey)
                ))
                .__(Grid.END)
                .__(Common.MOVE_CONFIRM_CHECK)
                .__end(commandBox);
        return true;
    }

    public static boolean printMotcleMergeBox(HtmlPrinter hp, CommandBox commandBox, Motcle motcle, BdfServer bdfServer, Lang workingLang, SubsetTree readSubsetTree, SubsetKey selectedSubsetKey) {
        SubsetKey checkedSelectedSubsetKey = testSubsetKey(readSubsetTree, selectedSubsetKey);
        if (checkedSelectedSubsetKey == null) {
            return false;
        }
        HtmlAttributes inputAttributes = hp.name(MotcleMergeCommand.MERGEMOTCLE_PARAMNAME).size("10")
                .populate(Appelant.motcle().wanted_code_id().limit(1).subsets(checkedSelectedSubsetKey));
        commandBox = commandBox.derive(MotcleMergeCommand.COMMANDNAME, MotcleMergeCommand.COMMANDKEY)
                .__(insert(motcle))
                .actionCssClass("action-Merge")
                .submitLocKey("_ submit.thesaurus.motclemerge");
        hp
                .__start(commandBox)
                .__(Grid.START)
                .__(Grid.textInputRow("_ label.thesaurus.mergemotcle", inputAttributes))
                .__(Grid.selectRow("_ label.thesaurus.mergethesaurus", hp.name(MotcleMergeCommand.MERGETHESAURUS_PARAMNAME).attr("data-appelant-role", "subset-select").attr("data-appelant-target", "#" + inputAttributes.id()),
                        SubsetTreeOptions.init(readSubsetTree, bdfServer, workingLang)
                                .onlyNames(true)
                                .withKeys(true)
                                .selectedSubsetKey(checkedSelectedSubsetKey)
                ))
                .__(Grid.END)
                .__(Common.MERGE_CONFIRM_CHECK)
                .__end(commandBox);
        return true;
    }

    private static boolean printRadioType(HtmlPrinter hp, String type, boolean checked) {
        hp
                .__(Grid.radioCell(ThesaurusHtmlUtils.getThesaurusTypeMessageKey(type), hp.name(ThesaurusCreationCommand.THESAURUSTYPE_PARAMNAME).value(type).checked(checked)));
        return true;
    }

    private static boolean printMotcleLabelTable(HtmlPrinter hp, @Nullable Motcle motcle, String paramPrefix, Langs langs, String messageKey) {
        Labels labels;
        if (motcle != null) {
            labels = motcle.getLabels();
        } else {
            labels = null;
        }
        hp
                .DT()
                .__localize(messageKey)
                ._DT()
                .DD()
                .__(Grid.START)
                .__(LangRows.init(paramPrefix, labels, langs).cols(60).rows(3))
                .__(Grid.END)
                ._DD();
        return true;
    }

    private static SubsetKey testSubsetKey(SubsetTree subsetTree, SubsetKey selectedSubsetKey) {
        SubsetKey firstSubsetKey = TreeUtils.getFirstSubsetKey(subsetTree);
        if (firstSubsetKey == null) {
            return null;
        }
        if (selectedSubsetKey == null) {
            return firstSubsetKey;
        }
        if (TreeUtils.containsSubsetKey(subsetTree, selectedSubsetKey)) {
            return selectedSubsetKey;
        }
        return firstSubsetKey;
    }

    private static boolean isFicheStyleUsed(Thesaurus thesaurus, BdfServer bdfServer) {
        SubsetKey thesaurusKey = thesaurus.getSubsetKey();
        UiManager uiManager = bdfServer.getUiManager();
        for (Corpus corpus : bdfServer.getFichotheque().getCorpusList()) {
            UiComponents uiComponents = uiManager.getMainUiComponents(corpus);
            for (UiComponent uiComponent : uiComponents.getUiComponentList()) {
                if (uiComponent instanceof SubsetIncludeUi) {
                    SubsetIncludeUi subsetIncludeUi = ((SubsetIncludeUi) uiComponent);
                    SubsetKey subsetKey = subsetIncludeUi.getSubsetKey();
                    if (subsetKey.equals(thesaurusKey)) {
                        if (subsetIncludeUi.matchInputType(BdfServerConstants.INPUT_FICHESTYLE)) {
                            return true;
                        }
                    }
                }
            }
        }
        return false;
    }

    private static boolean printStatusRow(HtmlPrinter hp, String status, String currentStatus) {
        hp
                .__(Grid.radioRow(getStatusMessageKey(status), hp.name(MotcleStatusCommand.STATUS_PARAMNAME).value(status).checked(currentStatus)));
        return true;
    }

    private static String getStatusMessageKey(String status) {
        switch (status) {
            case FichothequeConstants.ACTIVE_STATUS:
                return "_ label.thesaurus.status_active";
            case FichothequeConstants.GROUP_STATUS:
                return "_ label.thesaurus.status_group";
            case FichothequeConstants.OBSOLETE_STATUS:
                return "_ label.thesaurus.status_obsolete";
            default:
                throw new SwitchException("Unknown status: " + status);
        }
    }

}
