/* BdfServer_HtmlProducers - Copyright (c) 2011-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.corpus;

import fr.exemole.bdfserver.api.instruction.BdfParameters;
import fr.exemole.bdfserver.api.interaction.Domains;
import fr.exemole.bdfserver.api.interaction.domains.CorpusDomain;
import fr.exemole.bdfserver.commands.corpus.FieldOptionsCommand;
import fr.exemole.bdfserver.html.BdfHtmlUtils;
import fr.exemole.bdfserver.html.BdfServerHtmlProducer;
import fr.exemole.bdfserver.html.consumers.Grid;
import fr.exemole.bdfserver.html.jslib.BdfJsLibs;
import fr.exemole.bdfserver.htmlproducers.CommandBoxUtils;
import java.util.ArrayList;
import java.util.List;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.corpus.metadata.CorpusMetadata;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.corpus.metadata.FieldOptionConstants;
import net.fichotheque.sphere.Sphere;
import net.fichotheque.utils.CorpusMetadataUtils;
import net.fichotheque.utils.FichothequeUtils;
import net.fichotheque.utils.FieldOptionUtils;
import net.mapeadores.util.html.CommandBox;
import net.mapeadores.util.localisation.Langs;
import net.mapeadores.util.money.Currencies;
import net.mapeadores.util.money.ExtendedCurrency;
import net.mapeadores.util.text.MultiStringable;


/**
 *
 * @author Vincent Calame
 */
public class FieldOptionsFormHtmlProducer extends BdfServerHtmlProducer {

    private final Corpus corpus;
    private final List<CorpusField> geopointFieldList = new ArrayList<CorpusField>();

    public FieldOptionsFormHtmlProducer(BdfParameters bdfParameters, Corpus corpus) {
        super(bdfParameters);
        this.corpus = corpus;
        addJsLib(BdfJsLibs.COMMANDTEST);
        addJsLib(BdfJsLibs.COMMANDVEIL);
        addJsLib(BdfJsLibs.SUBSETCHANGE);
        addJsLib(BdfJsLibs.DEPLOY);
        addJsLib(BdfJsLibs.CODEMIRRORMODE);
        addThemeCss("corpus.css");
    }

    @Override
    public void printHtml() {
        CorpusMetadata corpusMetadata = corpus.getCorpusMetadata();
        start();
        BdfHtmlUtils.printSubsetHeader(this, bdfParameters, corpus, CorpusDomain.FIELD_OPTIONSFORM_PAGE);
        CorpusHtmlUtils.printCorpusToolbar(this, corpus, CorpusDomain.FIELD_OPTIONSFORM_PAGE, bdfServer);
        printCommandMessageUnit();
        CommandBox commandBox = CommandBox.init()
                .action(Domains.CORPUS)
                .family("CRP")
                .veil(true)
                .__(CommandBoxUtils.insert(corpus))
                .name(FieldOptionsCommand.COMMANDNAME)
                .lockey(FieldOptionsCommand.COMMANDKEY)
                .page(CorpusDomain.FIELD_OPTIONSFORM_PAGE)
                .submitLocKey("_ submit.corpus.fieldoptions");
        this
                .__start(commandBox)
                .__(printCorpusFieldOptions(corpusMetadata.getPropList(), "_ title.corpus.options_prop"))
                .__(printCorpusFieldOptions(corpusMetadata.getInfoList(), "_ title.corpus.options_info"))
                .__(printFicheOptions(corpusMetadata))
                .__end(commandBox);
        end();
    }

    private boolean printCorpusFieldOptions(List<CorpusField> list, String titleLocKey) {
        if (list.isEmpty()) {
            return false;
        }
        this
                .H2()
                .__localize(titleLocKey)
                ._H2()
                .DL("global-DL");
        for (CorpusField corpusField : list) {
            this
                    .DT()
                    .__(BdfHtmlUtils.printCodeMirrorSpan(this, corpusField, workingLang))
                    ._DT()
                    .DD()
                    .__(printFicheItemType(corpusField))
                    .__(Grid.START)
                    .__(printDefaultSphereKeyList(corpusField))
                    .__(printDisplay(corpusField))
                    .__(printCurrencyArray(corpusField))
                    .__(printAddressFieldArray(corpusField))
                    .__(printBaseUrl(corpusField))
                    .__(printSubfieldDisplay(corpusField))
                    .__(Grid.END)
                    ._DD();
        }
        this
                ._DL();
        return true;
    }


    private boolean printFicheItemType(CorpusField corpusField) {
        this
                .P("global-SubTitle")
                .__localize("_ label.corpus.ficheitemtype")
                .__colon()
                .__localize(CorpusHtmlUtils.getFicheItemMessageKey(corpusField.getFicheItemType()))
                ._P();
        return true;
    }

    private boolean printBaseUrl(CorpusField corpusField) {
        if (!FieldOptionUtils.testFieldOption(FieldOptionConstants.BASEURL_OPTION, corpusField)) {
            return false;
        }
        String value = corpusField.getStringOption(FieldOptionConstants.BASEURL_OPTION);
        if (value == null) {
            value = "";
        }
        String paramName = corpusField.getFieldString() + FieldOptionsCommand.BASEURL_SUFFIX;
        this
                .__(Grid.textInputRow("_ label.corpus.baseurl", name(paramName).value(value).size("60")));
        return true;
    }

    private boolean printDefaultSphereKeyList(CorpusField corpusField) {
        if (!FieldOptionUtils.testFieldOption(FieldOptionConstants.DEFAULTSPHEREKEY_OPTION, corpusField)) {
            return false;
        }
        SubsetKey currentDefault = corpusField.getDefaultSphereKey();
        String paramName = corpusField.getFieldString() + FieldOptionsCommand.DEFAULTSPHERE_SUFFIX;
        this
                .__(Grid.selectRow("_ label.corpus.defaultsphere", name(paramName),
                        () -> {
                            this
                                    .OPTION("", (currentDefault == null))
                                    .__localize("_ label.corpus.defaultsphere_user")
                                    ._OPTION();
                            for (Sphere sphere : fichotheque.getSphereList()) {
                                SubsetKey sphereKey = sphere.getSubsetKey();
                                boolean selected = ((currentDefault != null) && (currentDefault.equals(sphereKey)));
                                this
                                        .OPTION(sphereKey.getSubsetName(), selected)
                                        .__escape(FichothequeUtils.getTitleWithKey(sphere, workingLang))
                                        ._OPTION();
                            }
                        }));
        return true;
    }

    private boolean printSubfieldDisplay(CorpusField corpusField) {
        if (!FieldOptionUtils.testFieldOption(FieldOptionConstants.SUBFIELDDISPLAY_OPTION, corpusField)) {
            return false;
        }
        String paramName = corpusField.getFieldString() + FieldOptionsCommand.SUBFIELDDISPLAY_SUFFIX;
        boolean checked = corpusField.isSubfieldDisplay();
        this
                .__(Grid.checkboxRow("_ label.corpus.subfielddisplay", name(paramName).value("1").checked(checked)));
        return true;
    }

    private boolean printCurrencyArray(CorpusField corpusField) {
        if (!FieldOptionUtils.testFieldOption(FieldOptionConstants.CURRENCYARRAY_OPTION, corpusField)) {
            return false;
        }
        String paramName = corpusField.getFieldString() + FieldOptionsCommand.CURRENCIES_SUFFIX;
        Currencies currencies = corpusField.getCurrencies();
        String value = "";
        if (currencies != null) {
            StringBuilder buf = new StringBuilder();
            for (ExtendedCurrency currency : currencies) {
                buf.append(currency.getCurrencyCode());
                buf.append("; ");
            }
            value = buf.toString();
        }
        this
                .__(Grid.textInputRow("_ label.corpus.currencyarray", name(paramName).value(value).size("30")));
        return true;
    }

    private boolean printAddressFieldArray(CorpusField corpusField) {
        if (!FieldOptionUtils.testFieldOption(FieldOptionConstants.ADDRESSFIELDARRAY_OPTION, corpusField)) {
            return false;
        }
        geopointFieldList.add(corpusField);
        String paramName = corpusField.getFieldString() + FieldOptionsCommand.ADDRESSFIELDARRAY_SUFFIX;
        MultiStringable addressFieldNames = corpusField.getAddressFieldNames();
        String value = "";
        if (addressFieldNames != null) {
            value = addressFieldNames.toString(", ");
        }
        this
                .__(Grid.textInputRow("_ label.corpus.addressfieldarray", name(paramName).value(value).size("60")));
        return true;
    }

    private boolean printDisplay(CorpusField corpusField) {
        if (!FieldOptionUtils.testFieldOption(FieldOptionConstants.INFODISPLAY_OPTION, corpusField)) {
            return false;
        }
        this
                .__(Grid.checkboxRow("_ label.corpus.display", name(corpusField.getFieldString() + FieldOptionsCommand.BLOCKDISPLAY_SUFFIX).value("1").checked(corpusField.isBlockDisplayInfoField())));
        return true;
    }

    private boolean printFicheOptions(CorpusMetadata corpusMetadata) {
        this
                .H2()
                .__localize("_ title.corpus.options_global")
                ._H2()
                .__(Grid.START)
                .__(Grid.textAreaBlockRow("_ label.corpus.fieldgeneration", name(FieldOptionsCommand.FIELDGENERATION_PARAMNAME).cols(60).rows(6).attr("data-codemirror-mode", "tableexport"),
                        () -> {
                            this
                                    .__escape(corpusMetadata.getFieldGeneration().getRawString(), true);
                        }))
                .__(printGeolocalisationFieldSelect(corpusMetadata))
                .__(printLangScope(corpusMetadata.getCorpusField(FieldKey.LANG)))
                .__(Grid.END);
        return true;

    }

    private boolean printGeolocalisationFieldSelect(CorpusMetadata corpusMetadata) {
        if (geopointFieldList.isEmpty()) {
            return false;
        }
        CorpusField currentField = corpusMetadata.getGeolocalisationField();
        this
                .__(Grid.selectRow("_ label.corpus.geolocalisationfield", name(FieldOptionsCommand.GEOLOCALISATIONFIELD_PARAMNAME),
                        () -> {
                            this
                                    .OPTION("", (currentField == null))
                                    .__localize("_ label.corpus.nofield")
                                    ._OPTION();
                            for (CorpusField otherCorpusField : geopointFieldList) {
                                FieldKey fieldKey = otherCorpusField.getFieldKey();
                                boolean selected = ((currentField != null) && (currentField.equals(otherCorpusField)));
                                this
                                        .OPTION(fieldKey.getKeyString(), selected)
                                        .__escape(CorpusMetadataUtils.getFieldTitle(otherCorpusField, workingLang, true))
                                        ._OPTION();
                            }
                        }));
        return true;
    }

    private boolean printLangScope(CorpusField corpusField) {
        String radioName = corpusField.getFieldString() + FieldOptionsCommand.LANGSCOPE_SUFFIX;
        String langScope = corpusField.getLangScope();
        Langs langs = corpusField.getLangs();
        this
                .__(Grid.choiceSetRow("_ label.corpus.langscope",
                        () -> {
                            boolean multiChecked = false;
                            boolean nolangChecked = false;
                            boolean listChecked;
                            if (langScope.equals(FieldOptionConstants.LIST_SCOPE)) {
                                if (langs.size() == 1) {
                                    switch (langs.get(0).toString()) {
                                        case "mul":
                                            multiChecked = true;
                                            listChecked = false;
                                            break;
                                        case "zxx":
                                            nolangChecked = true;
                                            listChecked = false;
                                            break;
                                        default:
                                            listChecked = true;
                                    }
                                } else {
                                    listChecked = true;
                                }
                            } else {
                                listChecked = false;
                            }
                            String listValue;
                            if ((listChecked) && (langs != null)) {
                                listValue = langs.toString("; ");
                            } else {
                                listValue = "";
                            }
                            this
                                    .__(Grid.radioCell("_ label.corpus.langscope_config", name(radioName).value(FieldOptionsCommand.CONFIG_LANGSCOPE).checked(langScope)))
                                    .__(Grid.radioCell("_ label.corpus.langscope_all", name(radioName).value(FieldOptionsCommand.ALL_LANGSCOPE).checked(langScope)))
                                    .__(Grid.radioCell("_ label.corpus.langscope_mul", name(radioName).value(FieldOptionsCommand.MULTILANG_LANGSCOPE).checked(multiChecked)))
                                    .__(Grid.radioCell("_ label.corpus.langscope_zxx", name(radioName).value(FieldOptionsCommand.NOLINGUISTICCONTENT_LANGSCOPE).checked(nolangChecked)))
                                    .__(Grid.radioCell("_ label.corpus.langscope_list", name(radioName).value(FieldOptionsCommand.LIST_LANGSCOPE).checked(listChecked),
                                            () -> {
                                                this
                                                        .__(Grid.START)
                                                        .__(Grid.textInputRow("_ label.corpus.langarray", name(corpusField.getFieldString() + FieldOptionsCommand.LANGS_SUFFIX).value(listValue).size("30")))
                                                        .__(Grid.END);
                                            }));
                        }));
        return true;
    }


}
