/* BdfServer_Html - Copyright (c) 2020-2023 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.consumers;

import fr.exemole.bdfserver.api.BdfExtensionReference;
import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.interaction.InteractionConstants;
import fr.exemole.bdfserver.api.providers.MetadataPhraseDefProvider;
import fr.exemole.bdfserver.api.ui.MetadataPhraseDef;
import fr.exemole.bdfserver.tools.instruction.BdfInstructionUtils;
import fr.exemole.bdfserver.tools.ui.MetadataPhraseDefBuilder;
import fr.exemole.bdfserver.tools.ui.MetadataPhraseDefCatalog;
import fr.exemole.bdfserver.tools.ui.MetadataPhraseDefParser;
import java.text.ParseException;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import net.fichotheque.Metadata;
import net.fichotheque.Subset;
import net.fichotheque.namespaces.BdfSpace;
import net.mapeadores.util.attr.Attribute;
import net.mapeadores.util.attr.AttributeKey;
import net.mapeadores.util.html.HtmlAttributes;
import net.mapeadores.util.html.HtmlPrinter;
import net.mapeadores.util.localisation.Langs;
import net.mapeadores.util.localisation.Litteral;
import net.mapeadores.util.text.Labels;
import net.mapeadores.util.text.Phrase;


/**
 *
 * @author Vincent Calame
 */
public class MetadataPhrases implements Consumer<HtmlPrinter> {

    public final static String TITLE_PARAMPREFIX = "title/";
    public final static String NEWPHRASE_PARAMNAME = "newphrase";
    public final static String NEWPHRASE_PARAMPREFIX = "newphrase/";
    private final Metadata metadata;
    private final Langs langs;
    private final Object titleL10nObject;
    private final Map<String, MetadataPhraseDef> parametersMap = new LinkedHashMap<String, MetadataPhraseDef>();
    private boolean withNewPhrase = false;
    private String dlCssClasses = "global-DL";

    public MetadataPhrases(Metadata metadata, Langs langs, Object titleL10nObject) {
        this.metadata = metadata;
        this.langs = langs;
        this.titleL10nObject = titleL10nObject;
    }

    public boolean containsPhrase(String phraseName) {
        return parametersMap.containsKey(phraseName);
    }

    public MetadataPhrases addDef(MetadataPhraseDef metadataPhraseDef) {
        parametersMap.put(metadataPhraseDef.getName(), metadataPhraseDef);
        return this;
    }

    public MetadataPhrases populateFromAttributes(Subset subset) {
        if (subset != null) {
            AttributeKey attributeKey = BdfSpace.getPhrasesAttributeKey(subset.getSubsetKey());
            populateFromAttribute(subset.getFichotheque().getFichothequeMetadata().getAttributes().getAttribute(attributeKey));
        }
        populateFromAttribute(metadata.getAttributes().getAttribute(BdfSpace.PHRASES_KEY));
        return this;
    }

    private void populateFromAttribute(Attribute attribute) {
        if (attribute != null) {
            for (String value : attribute) {
                try {
                    MetadataPhraseDef def = MetadataPhraseDefParser.parse(value);
                    addDef(def);
                } catch (ParseException pe) {

                }
            }
        }
    }

    public MetadataPhrases withNewPhrase() {
        withNewPhrase = true;
        return this;
    }

    public MetadataPhrases dlCssClasses(String dlCssClasses) {
        this.dlCssClasses = dlCssClasses;
        return this;
    }

    public MetadataPhrases addExtensionPhraseDefList(BdfServer bdfServer) {
        for (BdfExtensionReference extensionReference : bdfServer.getExtensionManager().getBdfExtensionReferenceList()) {
            MetadataPhraseDefProvider provider = (MetadataPhraseDefProvider) extensionReference.getImplementation(MetadataPhraseDefProvider.class);
            if (provider != null) {
                for (MetadataPhraseDef phraseDef : provider.getMetadataPhraseDefList(metadata)) {
                    addDef(phraseDef);
                }
            }
        }
        return this;
    }

    @Override
    public void accept(HtmlPrinter hp) {
        Set<String> done = new HashSet<String>();
        hp
                .DL(dlCssClasses);
        addPhrase(hp, InteractionConstants.METATITLE_PARAMPREFIX, metadata.getTitleLabels(), titleL10nObject, 30);
        for (MetadataPhraseDef def : parametersMap.values()) {
            String name = def.getName();
            if (!done.contains(name)) {
                done.add(name);
                addPhrase(hp, def);
            }
        }
        for (Phrase phrase : metadata.getPhrases()) {
            String name = phrase.getName();
            if (!done.contains(name)) {
                done.add(name);
                addPhrase(hp, toMetadataPhraseDef(name));
            }
        }
        if (withNewPhrase) {
            HtmlAttributes inputAttributes = hp.name(InteractionConstants.NEWPHRASE_PARAMNAME).size("15");
            hp
                    .DT()
                    .SPAN("command-FlexInput")
                    .LABEL_for(inputAttributes.id())
                    .__localize("_ label.global.newphrase")
                    ._LABEL()
                    .SPAN("")
                    .__colon()
                    ._SPAN()
                    .INPUT_text(inputAttributes)
                    ._SPAN()
                    ._DT()
                    .DD()
                    .__(Grid.START)
                    .__(LangRows.init(InteractionConstants.NEWPHRASE_PARAMPREFIX, null, langs).cols(30))
                    .__(Grid.END)
                    ._DD();
        }
        hp
                ._DL();
    }

    private void addPhrase(HtmlPrinter hp, MetadataPhraseDef def) {
        String name = def.getName();
        addPhrase(hp, BdfInstructionUtils.getPhraseParamPrefix(name), metadata.getPhrases().getPhrase(name), def.getL10nObject(), def.getSize());
    }

    private void addPhrase(HtmlPrinter hp, String paramPrefix, Labels labels, Object l10nObject, int size) {
        if ((l10nObject instanceof Litteral) && (l10nObject.toString().startsWith("["))) {
            hp
                    .DT()
                    .CODE()
                    .__localize(l10nObject)
                    ._CODE()
                    ._DT();
        } else {
            hp
                    .DT()
                    .__localize(l10nObject)
                    ._DT();
        }
        hp
                .DD()
                .__(Grid.START)
                .__(LangRows.init(paramPrefix, labels, langs).cols(size))
                .__(Grid.END)
                ._DD();
    }

    public static MetadataPhrases init(Metadata metadata, Langs langs, String titleLocKey) {
        return new MetadataPhrases(metadata, langs, titleLocKey);
    }

    private MetadataPhraseDef toMetadataPhraseDef(String name) {
        MetadataPhraseDef def = MetadataPhraseDefCatalog.getMetadataPhraseDef(name);
        if (def != null) {
            return def;
        } else {
            return MetadataPhraseDefBuilder.init(name).toMetadataPhraseDef();
        }
    }

}
