/* 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;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.instruction.BdfParameters;
import fr.exemole.bdfserver.api.interaction.Domains;
import fr.exemole.bdfserver.api.interaction.InteractionConstants;
import fr.exemole.bdfserver.api.interaction.domains.AddendaDomain;
import fr.exemole.bdfserver.api.interaction.domains.AlbumDomain;
import fr.exemole.bdfserver.api.interaction.domains.CorpusDomain;
import fr.exemole.bdfserver.api.interaction.domains.SphereDomain;
import fr.exemole.bdfserver.api.interaction.domains.ThesaurusDomain;
import fr.exemole.bdfserver.api.namespaces.UiSpace;
import fr.exemole.bdfserver.api.subsettree.SubsetTree;
import fr.exemole.bdfserver.api.ui.CommentUi;
import fr.exemole.bdfserver.api.ui.DataUi;
import fr.exemole.bdfserver.api.ui.SpecialIncludeUi;
import fr.exemole.bdfserver.api.ui.SubsetIncludeUi;
import fr.exemole.bdfserver.api.users.BdfUser;
import fr.exemole.bdfserver.html.consumers.PageUnit;
import fr.exemole.bdfserver.html.consumers.SelectOption;
import fr.exemole.bdfserver.html.consumers.SubsetIcon;
import fr.exemole.bdfserver.html.consumers.SubsetTitle;
import fr.exemole.bdfserver.html.consumers.SubsetTreeOptions;
import fr.exemole.bdfserver.tools.L10nUtils;
import fr.exemole.bdfserver.tools.subsettree.TreeFilterEngine;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;
import net.fichotheque.Subset;
import net.fichotheque.SubsetItem;
import net.fichotheque.SubsetKey;
import net.fichotheque.addenda.Version;
import net.fichotheque.corpus.FicheMeta;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.include.ExtendedIncludeKey;
import net.fichotheque.permission.PermissionSummary;
import net.fichotheque.selection.SelectionDef;
import net.fichotheque.thesaurus.Motcle;
import net.fichotheque.thesaurus.MotcleIcon;
import net.fichotheque.utils.CorpusMetadataUtils;
import net.fichotheque.utils.FichothequeUtils;
import net.mapeadores.util.annotation.Nullable;
import net.mapeadores.util.attr.Attribute;
import net.mapeadores.util.html.HA;
import net.mapeadores.util.html.HtmlAttributes;
import net.mapeadores.util.html.HtmlPrinter;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.LocalisationUtils;
import net.mapeadores.util.primitives.FileLength;
import net.mapeadores.util.text.Idalpha;
import net.mapeadores.util.text.Label;
import net.mapeadores.util.text.Labels;


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

    private BdfHtmlUtils() {
    }

    public static boolean printMotcleTitle(HtmlPrinter hp, Motcle motcle, Lang lang) {
        return printMotcleTitle(hp, motcle, lang, true);
    }

    public static boolean printMotcleTitle(HtmlPrinter hp, Motcle motcle, Lang lang, boolean withId) {
        String idalpha = motcle.getIdalpha();
        if (idalpha != null) {
            if (!Idalpha.isSignificant(idalpha)) {
                hp
                        .SMALL()
                        .__escape('(')
                        .__escape(idalpha)
                        .__escape(')')
                        ._SMALL()
                        .__space();
            } else if (motcle.getThesaurus().getThesaurusMetadata().isBracketsIdalphaStyle()) {
                hp
                        .__escape("[")
                        .__escape(idalpha)
                        .__escape("]")
                        .__space();
            } else {
                hp
                        .__escape(idalpha)
                        .__dash();
            }
        }
        hp
                .__escape(motcle.getLabelString(lang));
        if ((idalpha == null) && (withId)) {
            hp
                    .__space()
                    .SMALL()
                    .__escape('(')
                    .__escape("id=")
                    .__append(motcle.getId())
                    .__escape(')')
                    ._SMALL();
        }
        return true;
    }

    public static boolean printMotcleIcon(HtmlPrinter hp, Motcle motcle, boolean withFontAwesome) {
        MotcleIcon motcleIcon = motcle.getMotcleIcon();
        if (motcleIcon == null) {
            return false;
        }
        hp
                .__(printMotcleIcon(hp, motcleIcon, withFontAwesome))
                .__space();
        return true;
    }

    public static boolean printMotcleIcon(HtmlPrinter hp, MotcleIcon motcleIcon, boolean withFontAwesome) {
        if (withFontAwesome) {
            if (!motcleIcon.hasFontAweson()) {
                withFontAwesome = false;
            }
        }
        HtmlAttributes ha = new HtmlAttributes();
        if (withFontAwesome) {
            ha.classes("fa-solid fa-" + motcleIcon.getFontAwesomeIcon());
        } else {
            ha.classes("global-Icon");
        }
        if (motcleIcon.hasColor()) {
            ha.style("color: " + motcleIcon.getColor());
        }
        hp
                .SPAN(ha);
        if (!withFontAwesome) {
            hp
                    .__escape(motcleIcon.getCharIcon("\u23F9"));
        }
        hp
                ._SPAN();
        return true;
    }

    public static String toParameterString(SubsetItem subsetItem) {
        SubsetKey subsetKey = subsetItem.getSubsetKey();
        StringBuilder buf = new StringBuilder();
        buf.append(subsetKey.getCategoryString());
        buf.append("=");
        buf.append(subsetKey.getSubsetName());
        buf.append("&");
        buf.append(InteractionConstants.ID_PARAMNAME);
        buf.append("=");
        buf.append(subsetItem.getId());
        return buf.toString();
    }

    public static List<SelectOption> toAvailableOptionList(List<SelectionDef> selectionDefList, Lang workingLang) {
        List<SelectOption> list = new ArrayList<SelectOption>();
        for (SelectionDef selectionDef : selectionDefList) {
            if (UiSpace.testHide(selectionDef.getAttributes(), "selectform")) {
                continue;
            }
            String name = selectionDef.getName();
            list.add(SelectOption.init(name).text(selectionDef.getTitle(workingLang)));
        }
        return list;
    }

    public static boolean startSubsetUnit(HtmlPrinter hp, BdfParameters bdfParameters, Subset subset, String page) {
        short subsetCategory = subset.getSubsetKey().getCategory();
        boolean isSubsetAdmin = bdfParameters.getPermissionSummary().isSubsetAdmin(subset.getSubsetKey());
        boolean withSubsetName = ((isSubsetAdmin) || (subsetCategory == SubsetKey.CATEGORY_SPHERE));
        if ((hp.isWithJavascript()) && (isSubsetAdmin)) {
            hp
                    .NAV("subset-ChangeSelect subset-list-ChangeSelect")
                    .__(printSubsetChangeSelect(hp, bdfParameters, subset.getSubsetKey(), page))
                    ._NAV();
        }
        hp
                .__(PageUnit.start().family(getFamilyCssClass(subsetCategory)).icon(SubsetIcon.getIcon(subsetCategory))
                        .title(SubsetTitle.init(subset, bdfParameters.getWorkingLang()).subsetName(withSubsetName)));
        return true;
    }

    public static boolean printSubsetHeader(HtmlPrinter hp, BdfParameters bdfParameters, Subset subset, String page) {
        boolean isSubsetAdmin = bdfParameters.getPermissionSummary().isSubsetAdmin(subset.getSubsetKey());
        if ((hp.isWithJavascript()) && (isSubsetAdmin)) {
            hp
                    .NAV("subset-ChangeSelect")
                    .__(printSubsetChangeSelect(hp, bdfParameters, subset.getSubsetKey(), page))
                    ._NAV();
        }
        hp
                .HEADER("subset-Header")
                .H1()
                .__(SubsetTitle.init(subset, bdfParameters.getWorkingLang()).subsetIcon(true).categoryPrefix(true).subsetName(isSubsetAdmin))
                ._H1()
                ._HEADER();
        return true;
    }

    public static boolean printSubsetChangeSelect(HtmlPrinter hp, BdfParameters bdfParameters, SubsetKey currentSubsetKey, String currentPage) {
        return printSubsetChangeSelect(hp, bdfParameters, currentSubsetKey, currentPage, true, true);
    }

    public static boolean printSubsetChangeSelect(HtmlPrinter hp, BdfParameters bdfParameters, SubsetKey currentSubsetKey, String currentPage, boolean admin, boolean withKeys) {
        BdfServer bdfServer = bdfParameters.getBdfServer();
        PermissionSummary permissionSummary = bdfParameters.getPermissionSummary();
        if (currentPage == null) {
            currentPage = "";
        }
        short subsetCategory = currentSubsetKey.getCategory();
        String categoryName = SubsetKey.categoryToString(subsetCategory);
        SubsetTree originalSubsetTree = bdfServer.getTreeManager().getSubsetTree(subsetCategory);
        SubsetTree filteredSubsetTree;
        if (admin) {
            filteredSubsetTree = TreeFilterEngine.admin(permissionSummary, originalSubsetTree);
        } else {
            filteredSubsetTree = TreeFilterEngine.read(permissionSummary, originalSubsetTree);
        }
        if (withKeys) {
            hp
                    .SPAN("subset-SmallLabel")
                    .__localize(getSubsetCategoryLocKey(subsetCategory))
                    .__colon()
                    ._SPAN();
        }
        HtmlAttributes selectAttr = HA.name(categoryName).attr("data-subsetchange-role", "select").attr("data-subsetchange-page", currentPage);
        hp
                .SELECT(selectAttr)
                .__(SubsetTreeOptions.init(filteredSubsetTree, bdfServer, bdfParameters.getWorkingLang())
                        .onlyNames(true)
                        .withKeys(withKeys)
                        .selectedSubsetKey(currentSubsetKey)
                )
                ._SELECT();
        return true;
    }

    public static boolean printCroisementRemoveWarning(HtmlPrinter hp, SubsetKey subsetKey, PermissionSummary permissionSummary) {
        if (permissionSummary.getWriteLevel(subsetKey) == PermissionSummary.SUMMARYLEVEL_3_CROISEMENT_TEST) {
            hp
                    .P()
                    .EM()
                    .__localize("_ warning.addenda.allcroisementremove")
                    ._EM()
                    ._P();
            return true;
        } else {
            return false;
        }
    }

    public static boolean printDocumentVersionSize(HtmlPrinter hp, Version version, Locale formatLocale) {
        FileLength fileLength = version.getFileLength();
        NumberFormat format = NumberFormat.getInstance(formatLocale);
        float value = fileLength.getRoundedValue();
        hp
                .__escape(format.format(value))
                .__nonBreakableSpace();
        if (fileLength.getRoundType() == FileLength.KB_ROUND) {
            hp
                    .__escape(LocalisationUtils.getKibiOctet(formatLocale));
        } else {
            hp
                    .__escape(LocalisationUtils.getMebiOctet(formatLocale));
        }
        return true;
    }

    public static String getLabelString(@Nullable Labels labels, Lang lang) {
        if (labels == null) {
            return "";
        }
        Label label = labels.getLabel(lang);
        if (label == null) {
            return "";
        }
        return label.getLabelString();
    }

    public static boolean printCodeMirrorSpan(HtmlPrinter hp, CorpusField corpusField, Lang lang) {
        String title = L10nUtils.getCorpusFieldTitle(corpusField, lang);
        switch (corpusField.getCategory()) {
            case FieldKey.SPECIAL_CATEGORY:
                hp
                        .SPAN("cm-component-field")
                        .__escape(corpusField.getFieldString())
                        ._SPAN();
                break;
            default:
                hp
                        .SPAN("cm-component-field")
                        .__escape(corpusField.getCategoryString())
                        ._SPAN()
                        .SPAN("cm-quote")
                        .__escape('_')
                        .__escape(corpusField.getFieldName())
                        ._SPAN();
        }
        if (title != null) {
            hp
                    .__space()
                    .SPAN("cm-comment")
                    .__escape('(')
                    .__escape(title)
                    .__escape(')')
                    ._SPAN();
        }
        return true;
    }


    public static boolean printCodeMirrorSpan(HtmlPrinter hp, SubsetIncludeUi includeUi, BdfServer bdfServer, Lang lang) {
        ExtendedIncludeKey includeKey = includeUi.getExtendedIncludeKey();
        SubsetKey subsetKey = includeKey.getSubsetKey();
        String mode = includeKey.getMode();
        int weightFilter = includeKey.getWeightFilter();
        String title = L10nUtils.getIncludeTitle(bdfServer, includeUi, lang);
        if (includeKey.isMaster()) {
            hp
                    .SPAN("cm-qualifier")
                    .__escape("_master_")
                    ._SPAN();
        }
        hp
                .SPAN("cm-component-subset")
                .__escape(subsetKey.getCategoryString())
                ._SPAN()
                .SPAN("cm-quote")
                .__escape('_')
                .__escape(subsetKey.getSubsetName())
                ._SPAN();
        if (mode.length() > 0) {
            hp
                    .SPAN("cm-def")
                    .__escape('_')
                    .__escape(mode)
                    ._SPAN();
        }
        if (weightFilter > 0) {
            hp
                    .SPAN("cm-number")
                    .__escape('_')
                    .__append(weightFilter)
                    ._SPAN();
        }
        if (title != null) {
            hp
                    .__space()
                    .SPAN("cm-comment")
                    .__escape('(')
                    .__escape(title)
                    .__escape(')')
                    ._SPAN();
        }
        return true;
    }

    public static boolean printCodeMirrorSpan(HtmlPrinter hp, SpecialIncludeUi includeUi, BdfServer bdfServer, Lang lang) {
        String title = L10nUtils.getIncludeTitle(bdfServer, includeUi, lang);
        hp
                .SPAN("cm-component-subset")
                .__escape(includeUi.getName())
                ._SPAN();
        if (title != null) {
            hp
                    .__space()
                    .SPAN("cm-comment")
                    .__escape('(')
                    .__escape(title)
                    .__escape(')')
                    ._SPAN();
        }
        return true;
    }

    public static boolean printCodeMirrorSpan(HtmlPrinter hp, DataUi dataUi, Lang lang) {
        String title = L10nUtils.getDataTitle(dataUi, lang);
        hp
                .SPAN("cm-component-data")
                .__escape("data")
                ._SPAN()
                .SPAN("cm-quote")
                .__escape("_")
                .__escape(dataUi.getDataName())
                ._SPAN();
        if (title != null) {
            hp
                    .__space()
                    .SPAN("cm-comment")
                    .__escape('(')
                    .__escape(title)
                    .__escape(')')
                    ._SPAN();
        }
        return true;
    }

    public static boolean printCodeMirrorSpan(HtmlPrinter hp, CommentUi commentUi, Lang lang) {
        String title = L10nUtils.getCommentTitle(commentUi, lang);
        hp
                .SPAN("cm-component-comment")
                .__escape("comment")
                ._SPAN()
                .SPAN("cm-quote")
                .__escape("_")
                .__escape(commentUi.getCommentName())
                ._SPAN();
        if (title != null) {
            hp
                    .__space()
                    .SPAN("cm-comment")
                    .__escape('(')
                    .__escape(title)
                    .__escape(')')
                    ._SPAN();
        }
        return true;
    }

    public static String getSubsetCategoryLocKey(short subsetCategory) {
        switch (subsetCategory) {
            case SubsetKey.CATEGORY_CORPUS:
                return "_ label.global.corpus";
            case SubsetKey.CATEGORY_THESAURUS:
                return "_ label.global.thesaurus";
            case SubsetKey.CATEGORY_SPHERE:
                return "_ label.global.sphere";
            case SubsetKey.CATEGORY_ADDENDA:
                return "_ label.global.addenda";
            case SubsetKey.CATEGORY_ALBUM:
                return "_ label.global.album";
            default:
                throw new IllegalArgumentException("wrong subsetCategory value");
        }
    }

    public static String getSubsetCollectionLocKey(short subsetCategory) {
        switch (subsetCategory) {
            case SubsetKey.CATEGORY_ADDENDA:
                return "_ title.global.addenda_collection";
            case SubsetKey.CATEGORY_ALBUM:
                return "_ title.global.album_collection";
            case SubsetKey.CATEGORY_CORPUS:
                return "_ title.global.corpus_collection";
            case SubsetKey.CATEGORY_THESAURUS:
                return "_ title.global.thesaurus_collection";
            case SubsetKey.CATEGORY_SPHERE:
                return "_ title.global.sphere_collection";
            default:
                throw new IllegalArgumentException("wrong subsetCategory value");
        }
    }

    public static String getFamilyCssClass(short subsetCategory) {
        switch (subsetCategory) {
            case SubsetKey.CATEGORY_CORPUS:
                return "family-CRP";
            case SubsetKey.CATEGORY_THESAURUS:
                return "family-THS";
            case SubsetKey.CATEGORY_SPHERE:
                return "family-SPH";
            case SubsetKey.CATEGORY_ADDENDA:
                return "family-ADD";
            case SubsetKey.CATEGORY_ALBUM:
                return "family-ALB";
            default:
                throw new IllegalArgumentException("wrong croisementCategory value");
        }
    }

    public static String getDomain(short subsetCategory) {
        switch (subsetCategory) {
            case SubsetKey.CATEGORY_CORPUS:
                return Domains.CORPUS;
            case SubsetKey.CATEGORY_THESAURUS:
                return Domains.THESAURUS;
            case SubsetKey.CATEGORY_SPHERE:
                return Domains.SPHERE;
            case SubsetKey.CATEGORY_ADDENDA:
                return Domains.ADDENDA;
            case SubsetKey.CATEGORY_ALBUM:
                return Domains.ALBUM;
            default:
                throw new IllegalArgumentException("wrong croisementCategory value");
        }
    }

    public static String getPage(short subsetCategory) {
        switch (subsetCategory) {
            case SubsetKey.CATEGORY_CORPUS:
                return CorpusDomain.CORPUS_PAGE;
            case SubsetKey.CATEGORY_THESAURUS:
                return ThesaurusDomain.THESAURUS_PAGE;
            case SubsetKey.CATEGORY_SPHERE:
                return SphereDomain.SPHERE_PAGE;
            case SubsetKey.CATEGORY_ADDENDA:
                return AddendaDomain.ADDENDA_PAGE;
            case SubsetKey.CATEGORY_ALBUM:
                return AlbumDomain.ALBUM_PAGE;
            default:
                throw new IllegalArgumentException("wrong croisementCategory value");
        }
    }


    public static String getAddCss(short subsetCategory) {
        switch (subsetCategory) {
            case SubsetKey.CATEGORY_CORPUS:
                return "action-CorpusAdd";
            case SubsetKey.CATEGORY_THESAURUS:
                return "action-ThesaurusAdd";
            case SubsetKey.CATEGORY_SPHERE:
                return "action-SphereAdd";
            case SubsetKey.CATEGORY_ADDENDA:
                return "action-AddendaAdd";
            case SubsetKey.CATEGORY_ALBUM:
                return "action-AlbumAdd";
            default:
                throw new IllegalArgumentException("wrong croisementCategory value");
        }
    }

    public static boolean printItemCount(HtmlPrinter hp, BdfUser bdfUser, int count) {
        hp
                .SPAN(HA.classes("subset-ItemCount").addClass((count == 0), "subset-None"))
                .__escape('(')
                .__escape(bdfUser.format(count))
                .__escape(')')
                ._SPAN();
        return true;
    }

    public static boolean printAttributeToText(HtmlPrinter hp, Attribute attribute) {
        if (attribute == null) {
            return false;
        }
        for (String value : attribute) {
            hp
                    .__escape(value)
                    .__newLine();
        }
        return true;
    }

    public static boolean printFicheTitle(HtmlPrinter hp, String title, boolean discarded, SubsetItem masterItem, Lang workingLang, Locale formatLocale) {
        hp
                .H1()
                .SPAN("subset-FicheTitle");
        if (discarded) {
            hp
                    .SPAN("subset-Discarded")
                    .__escape(title)
                    ._SPAN();
        } else {
            hp
                    .__escape(title);
        }
        if (masterItem != null) {
            hp
                    .BR()
                    .SPAN("subset-MasterItem");
            if (masterItem instanceof Motcle) {
                hp
                        .__localize("_ label.corpus.satellite_motcle")
                        .__colon()
                        .__(printMotcleTitle(hp, (Motcle) masterItem, workingLang, false))
                        .__escape(" (")
                        .__localize("_ label.global.thesaurus")
                        .__colon()
                        .__escape(FichothequeUtils.getTitle(masterItem.getSubset(), workingLang))
                        .__escape(")");
            } else if (masterItem instanceof FicheMeta) {
                FicheMeta masterFicheMeta = (FicheMeta) masterItem;
                hp
                        .__localize("_ label.corpus.satellite_fiche")
                        .__colon()
                        .SPAN(HA.classes(masterFicheMeta.isDiscarded(), "subset-Discarded"))
                        .__escape(CorpusMetadataUtils.getFicheTitle(masterFicheMeta, workingLang, formatLocale))
                        ._SPAN();
            }

            hp
                    ._SPAN();
        }
        hp
                ._SPAN()
                ._H1();
        return true;
    }

}
