/* 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.externalsource.ExternalSourceType;
import fr.exemole.bdfserver.api.instruction.BdfParameters;
import fr.exemole.bdfserver.api.interaction.Domains;
import fr.exemole.bdfserver.api.interaction.domains.ThesaurusDomain;
import fr.exemole.bdfserver.commands.thesaurus.ThesaurusPolicyCommand;
import fr.exemole.bdfserver.html.BdfHtmlUtils;
import fr.exemole.bdfserver.html.BdfServerHtmlProducer;
import fr.exemole.bdfserver.html.consumers.Grid;
import fr.exemole.bdfserver.html.consumers.attributes.Deploy;
import fr.exemole.bdfserver.html.jslib.BdfJsLibs;
import fr.exemole.bdfserver.htmlproducers.CommandBoxUtils;
import fr.exemole.bdfserver.tools.externalsource.ExternalSourceUtils;
import java.util.List;
import net.fichotheque.SubsetKey;
import net.fichotheque.externalsource.ExternalSourceDef;
import net.fichotheque.permission.PermissionSummary;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.thesaurus.metadata.ThesaurusMetadata;
import net.fichotheque.thesaurus.policies.DynamicEditPolicy;
import net.fichotheque.utils.FichothequeUtils;
import net.fichotheque.utils.ThesaurusUtils;
import net.mapeadores.util.html.CommandBox;
import net.mapeadores.util.html.HtmlAttributes;
import net.mapeadores.util.localisation.Litteral;


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

    private final PermissionSummary permissionSummary;
    private final Thesaurus thesaurus;

    public ThesaurusMetadataFormHtmlProducer(BdfParameters bdfParameters, Thesaurus thesaurus) {
        super(bdfParameters);
        this.permissionSummary = bdfParameters.getPermissionSummary();
        this.thesaurus = thesaurus;
        addJsLib(BdfJsLibs.COMMANDTEST);
        addJsLib(BdfJsLibs.COMMANDVEIL);
        addJsLib(BdfJsLibs.DEPLOY);
        addJsLib(BdfJsLibs.SUBSETCHANGE);
        addThemeCss("thesaurus.css");
    }

    @Override
    public void printHtml() {
        start();
        BdfHtmlUtils.printSubsetHeader(this, bdfParameters, thesaurus, ThesaurusDomain.THESAURUS_METADATAFORM_PAGE);
        ThesaurusHtmlUtils.printThesaurusToolbar(this, ThesaurusDomain.THESAURUS_METADATAFORM_PAGE, thesaurus);
        printCommandMessageUnit();
        CommandBox commandBox = CommandBox.init()
                .action(Domains.THESAURUS)
                .family("THS")
                .veil(true)
                .page(ThesaurusDomain.THESAURUS_METADATAFORM_PAGE);
        ThesaurusCommandBoxUtils.printThesaurusPhrasesBox(this, commandBox, thesaurus, bdfServer);
        ThesaurusCommandBoxUtils.printThesaurusLangListBox(this, commandBox, thesaurus, bdfServer);
        if (permissionSummary.isFichothequeAdmin()) {
            printPolicy(commandBox);
        }
        end();
    }

    private void printPolicy(CommandBox commandBox) {
        DynamicEditPolicy policy = bdfServer.getPolicyManager().getPolicyProvider().getDynamicEditPolicy(thesaurus);
        commandBox = commandBox.derive(ThesaurusPolicyCommand.COMMANDNAME, ThesaurusPolicyCommand.COMMANDKEY)
                .__(CommandBoxUtils.insert(thesaurus))
                .submitLocKey("_ submit.thesaurus.thesauruspolicy");
        this
                .__start(commandBox)
                .__(Grid.START)
                .__(printNoneRadio(policy))
                .__(printSupplementaryPolicies(policy))
                .__(printExternalRadio(policy))
                .__(Grid.END)
                .__end(commandBox);
    }

    private boolean printSupplementaryPolicies(DynamicEditPolicy policy) {
        short thesaurusType = thesaurus.getThesaurusMetadata().getThesaurusType();
        switch (thesaurusType) {
            case ThesaurusMetadata.MULTI_TYPE: {
                List<Thesaurus> babelienList = ThesaurusUtils.getBabelienThesaurusList(bdfServer.getFichotheque());
                if (babelienList.isEmpty()) {
                    return false;
                }
                SubsetKey currentTransferKey = null;
                if (policy instanceof DynamicEditPolicy.Transfer) {
                    currentTransferKey = ((DynamicEditPolicy.Transfer) policy).getTransferThesaurusKey();
                }
                this
                        .__(printTransferRadio(currentTransferKey, babelienList));
                return true;
            }
            case ThesaurusMetadata.BABELIEN_TYPE: {
                List<Thesaurus> babelienList = ThesaurusUtils.getBabelienThesaurusList(bdfServer.getFichotheque());
                List<Thesaurus> noIdalphaList = ThesaurusUtils.getNoIdalphaThesaurusList(bdfServer.getFichotheque());
                this
                        .__if((babelienList.size() >= 0), () -> {
                            SubsetKey currentTransferKey = null;
                            if (policy instanceof DynamicEditPolicy.Transfer) {
                                currentTransferKey = ((DynamicEditPolicy.Transfer) policy).getTransferThesaurusKey();
                            }
                            this
                                    .__(printTransferRadio(currentTransferKey, babelienList));
                        })
                        .__(printAllowRadio(policy))
                        .__if((noIdalphaList.size() >= 0), () -> {
                            this
                                    .__(printCheckRadio(getCheckList(policy), noIdalphaList));
                        });
                return true;
            }
            default:
                return false;
        }
    }

    private boolean printPolicyRadio(String policyValue, boolean checked, String messageKey) {
        HtmlAttributes radio = policyRadio(policyValue).checked(checked);
        this
                .__(Grid.radioRow(messageKey, radio));
        return true;
    }

    private boolean printNoneRadio(DynamicEditPolicy policy) {
        boolean checked = (policy instanceof DynamicEditPolicy.None);
        return printPolicyRadio(ThesaurusPolicyCommand.POLICY_NONE_PARAMVALUE, checked, "_ label.thesaurus.policy_none");
    }

    private boolean printAllowRadio(DynamicEditPolicy policy) {
        boolean checked = (policy instanceof DynamicEditPolicy.Allow);
        return printPolicyRadio(ThesaurusPolicyCommand.POLICY_ALLOW_PARAMVALUE, checked, "_ label.thesaurus.policy_allow");
    }

    private boolean printTransferRadio(SubsetKey currentTransferKey, List<Thesaurus> transferList) {
        String detailId = generateId();
        boolean checked = (currentTransferKey != null);
        HtmlAttributes radio = policyRadio(ThesaurusPolicyCommand.POLICY_TRANSFER_PARAMVALUE).checked(checked).populate(Deploy.radio(detailId));
        this
                .__(Grid.radioRow("_ label.thesaurus.policy_transfer", radio,
                        () -> {
                            this
                                    .DIV(Grid.detailPanelTable().id(detailId).addClass(!checked, "hidden"))
                                    .__(Grid.selectRow("_ label.global.thesaurus", name(ThesaurusPolicyCommand.TRANSFERKEY_PARAMNAME), () -> {
                                        for (Thesaurus transferThesaurus : transferList) {
                                            SubsetKey transferKey = transferThesaurus.getSubsetKey();
                                            this
                                                    .OPTION(transferKey.getSubsetName(), ((currentTransferKey != null) && (transferKey.equals(currentTransferKey))))
                                                    .__escape(FichothequeUtils.getTitleWithKey(transferThesaurus, workingLang))
                                                    ._OPTION();
                                        }
                                    }))
                                    ._DIV();
                        }));
        return true;
    }

    private boolean printCheckRadio(List<SubsetKey> currentList, List<Thesaurus> availableList) {
        String detailId = generateId();
        boolean checked = (currentList != null);
        HtmlAttributes radio = policyRadio(ThesaurusPolicyCommand.POLICY_CHECK_PARAMVALUE).checked(checked).populate(Deploy.radio(detailId));
        this
                .__(Grid.radioRow("_ label.thesaurus.policy_check", radio,
                        () -> {
                            this
                                    .DIV(Grid.detailPanelTable().id(detailId).addClass(!checked, "hidden"))
                                    .__(Grid.selectRow("_ label.global.thesaurus", name(ThesaurusPolicyCommand.CHECKKEYLIST_PARAMNAME).size("5").multiple(true), () -> {
                                        for (Thesaurus availableThesaurus : availableList) {
                                            SubsetKey availableKey = availableThesaurus.getSubsetKey();
                                            this
                                                    .OPTION(availableKey.getSubsetName(), ((currentList != null) && (currentList.contains(availableKey))))
                                                    .__escape(FichothequeUtils.getTitleWithKey(availableThesaurus, workingLang))
                                                    ._OPTION();
                                        }
                                    }))
                                    ._DIV();
                        }));
        return true;
    }

    private boolean printExternalRadio(DynamicEditPolicy policy) {
        List<ExternalSourceType> typeList = ExternalSourceUtils.getAvalaibleTypeList(bdfServer, thesaurus);
        ExternalSourceDef currentExternalSourceDef;
        boolean here = false;
        if (policy instanceof DynamicEditPolicy.External) {
            currentExternalSourceDef = ((DynamicEditPolicy.External) policy).getExternalSourceDef();
            for (ExternalSourceType type : typeList) {
                if (type.getName().equals(currentExternalSourceDef.getType())) {
                    here = true;
                }
            }
        } else {
            currentExternalSourceDef = null;
        }
        if ((typeList.isEmpty()) && (currentExternalSourceDef == null)) {
            return false;
        }
        boolean unknwonDef = ((currentExternalSourceDef != null) && (!here));
        String detailId = generateId();
        boolean checked = (currentExternalSourceDef != null);
        HtmlAttributes radio = policyRadio(ThesaurusPolicyCommand.POLICY_EXTERNAL_PARAMVALUE).checked(checked).populate(Deploy.radio(detailId));
        this
                .__(Grid.radioRow("_ label.thesaurus.policy_external", radio,
                        () -> {
                            this
                                    .DIV(Grid.detailPanelTable().id(detailId).addClass(!checked, "hidden"));
                            for (ExternalSourceType type : typeList) {
                                this
                                        .__(printExternalType(type, currentExternalSourceDef));
                            }
                            if (unknwonDef) {
                                this
                                        .printUnknownDef(currentExternalSourceDef);
                            }
                            this
                                    ._DIV();
                        }));
        return true;
    }

    private HtmlAttributes policyRadio(String policyValue) {
        return name(ThesaurusPolicyCommand.POLICY_PARAMNAME).value(policyValue);
    }

    private List<SubsetKey> getCheckList(DynamicEditPolicy policy) {
        if (!(policy instanceof DynamicEditPolicy.Check)) {
            return null;
        }
        return ((DynamicEditPolicy.Check) policy).getCheckSubseKeyList();
    }

    private boolean printExternalType(ExternalSourceType type, ExternalSourceDef currentExternalSourceDef) {
        boolean isCurrent;
        if ((currentExternalSourceDef != null) && (currentExternalSourceDef.getType().equals(type.getName()))) {
            isCurrent = true;
        } else {
            isCurrent = false;
        }
        String typeName = type.getName();
        String detailId = generateId();
        List<ExternalSourceType.Param> paramList = type.getParamList();
        HtmlAttributes radio = name(ThesaurusPolicyCommand.EXTERNALTYPE_PARAMNAME).value(typeName).checked(isCurrent);
        Runnable runnable;
        if (!paramList.isEmpty()) {
            radio.populate(Deploy.radio(detailId));
            runnable = () -> {
                this
                        .DIV(Grid.detailPanelTable().id(detailId).addClass(!isCurrent, "hidden"));
                for (ExternalSourceType.Param param : paramList) {
                    String value = "";
                    if (isCurrent) {
                        value = currentExternalSourceDef.getParam(param.getName());
                    }
                    this
                            .__(Grid.textInputRow(param.getL10nObject(), name(ThesaurusPolicyCommand.EXTERNAL_PARAMPREFIX + type.getName() + "|" + param.getName()).value(value)));
                }
                this
                        ._DIV();
            };
        } else {
            runnable = null;
        }
        this
                .__(Grid.radioRow(type.getL10nObject(), radio, runnable));
        return true;
    }

    private boolean printUnknownDef(ExternalSourceDef externalSourceDef) {
        String sourceType = externalSourceDef.getType();
        String detailId = generateId();
        HtmlAttributes radio = name(ThesaurusPolicyCommand.EXTERNALTYPE_PARAMNAME).value(sourceType).checked(true).populate(Deploy.radio(detailId));
        this
                .__(Grid.radioRow(new Litteral(sourceType), radio,
                        () -> {
                            this
                                    .DIV(Grid.detailPanelTable().id(detailId));
                            for (String paramName : externalSourceDef.getParamNameSet()) {
                                String value = externalSourceDef.getParam(paramName);
                                this
                                        .__(Grid.textInputRow(new Litteral(paramName), name(ThesaurusPolicyCommand.EXTERNAL_PARAMPREFIX + sourceType + "|" + paramName).value(value)));
                            }
                            this
                                    ._DIV();
                        }));
        return true;
    }

}
