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

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.interaction.InteractionConstants;
import fr.exemole.bdfserver.api.namespaces.BdfSessionSpace;
import fr.exemole.bdfserver.api.session.AuthenticationException;
import fr.exemole.bdfserver.api.session.LoginParameters;
import fr.exemole.bdfserver.html.consumers.Button;
import fr.exemole.bdfserver.html.consumers.Grid;
import fr.exemole.bdfserver.html.consumers.PageUnit;
import fr.exemole.bdfserver.tools.storage.StorageUtils;
import fr.exemole.bdfserver.tools.subsettree.TreeUtils;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.function.Consumer;
import net.fichotheque.SubsetKey;
import net.fichotheque.metadata.FichothequeMetadata;
import net.fichotheque.sphere.Sphere;
import net.fichotheque.utils.FichothequeMetadataUtils;
import net.fichotheque.utils.FichothequeUtils;
import net.mapeadores.util.html.ConsumerFactory;
import net.mapeadores.util.html.HA;
import net.mapeadores.util.html.HtmlAttributes;
import net.mapeadores.util.html.HtmlConstants;
import net.mapeadores.util.html.HtmlPrinter;
import net.mapeadores.util.localisation.LangPreference;
import net.mapeadores.util.logging.CommandMessage;
import net.mapeadores.util.request.RequestMap;
import net.mapeadores.util.text.Label;
import net.mapeadores.util.text.Phrase;


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

    private final static Consumer<HtmlPrinter> LOGIN_SUBMIT = Button.submit("_ submit.session.login");
    private final static Consumer<HtmlPrinter> LOGIN_ICON = ConsumerFactory.emptySpan("global-button-Icon login-Icon");
    private final LoginParameters loginParameters;
    private final String reversePath;

    public LoginHtmlProducer(BdfServer bdfServer, LangPreference langPreference, LoginParameters loginParameters) {
        super(bdfServer, langPreference);
        setWithJavascript(true);
        this.loginParameters = loginParameters;
        reversePath = loginParameters.getReversePath();
        scanIcons();
        setReversePath(reversePath);
        addThemeCss("login.css");
        setBodyCssClass("global-body-Transparent");
    }

    @Override
    public void printHtml() {
        String title = getTitle();
        start(title);
        this
                .__(printLogo())
                .H1("login-Title")
                .__escape(title)
                ._H1();
        this
                .P("login-Text login-Subtitle")
                .__(printSubtitleMessage())
                ._P();
        this
                .DIV("login-Block")
                .__(PageUnit.start("_ title.session.loginfieldset").sectionCss("unit-Unit login-Unit").icon(LOGIN_ICON))
                .FORM_post(loginParameters.getFormAction())
                .__(Grid.START)
                .__(printSphereRow())
                .__(Grid.textInputRow("_ label.session.login", name(InteractionConstants.BDF_LOGIN_PARAMNAME).value(getDefaultValue(InteractionConstants.BDF_LOGIN_PARAMNAME, InteractionConstants.BDF_DEFAULT_LOGIN_PARAMNAME)).classes("login-Input")))
                .__(Grid.passwordInputRow("_ label.session.password", name(InteractionConstants.BDF_PASSWORD_PARAMNAME).classes("login-Input")))
                .__(Grid.END)
                .NOSCRIPT()
                .INPUT_hidden(InteractionConstants.BDF_NOSCRIPT_PARAMNAME, "1")
                ._NOSCRIPT()
                .DIV("login-Text")
                .__(LOGIN_SUBMIT)
                ._DIV()
                .__(printCurrentParameters())
                ._FORM()
                .__(printAuthenticationException())
                .__(PageUnit.END)
                ._DIV();
        end();
    }

    private boolean printLogo() {
        if (!bdfServer.getResourceStorages().containsResource(StorageUtils.LOGO)) {
            return false;
        }
        this
                .IMG(HA.src(reversePath + StorageUtils.LOGO.toString()).alt("logo").classes("login-Logo"));
        return true;
    }

    private boolean printSubtitleMessage() {
        CommandMessage commandMessage = loginParameters.getCommandMessage();
        if (commandMessage != null) {
            this
                    .__localize(commandMessage);
        } else {
            this
                    .__localize("_ info.session.newsession");
        }
        return true;
    }


    private boolean printSphereRow() {
        String defaultValue = getDefaultValue(InteractionConstants.BDF_SPHERE_PARAMNAME, InteractionConstants.BDF_DEFAULT_SPHERE_PARAMNAME);
        if (defaultValue.isEmpty()) {
            SubsetKey defaultSphereKey = loginParameters.getDefaultSphereKey();
            if (defaultSphereKey != null) {
                defaultValue = defaultSphereKey.getSubsetName();
            }
        }
        List<Sphere> sphereList = checkSphereList();
        int size = sphereList.size();
        if (size == 0) {
            return false;
        }
        if (size == 1) {
            String sphereName = sphereList.get(0).getSubsetName();
            if (!BdfSessionSpace.showUniqueRow(fichotheque)) {
                this
                        .INPUT_hidden(InteractionConstants.BDF_SPHERE_PARAMNAME, sphereName);
                return true;
            } else {
                defaultValue = sphereName;
            }
        }
        String currentSphereName = defaultValue;
        this
                .__(Grid.selectRow("_ label.session.sphere", name(InteractionConstants.BDF_SPHERE_PARAMNAME), () -> {
                    for (Sphere sphere : sphereList) {
                        String name = sphere.getSubsetName();
                        this
                                .OPTION(name, (name.equals(currentSphereName)))
                                .__escape(FichothequeUtils.getTitleWithKey(sphere, workingLang))
                                ._OPTION();
                    }
                }));
        return true;
    }

    private String getDefaultValue(String paramName, String defaultParamName) {
        RequestMap requestMap = loginParameters.getRequestMap();
        String defaultValue = requestMap.getParameter(paramName);
        if (defaultValue == null) {
            defaultValue = requestMap.getParameter(defaultParamName);
        }
        if (defaultValue == null) {
            defaultValue = "";
        } else {
            defaultValue = defaultValue.trim();
        }
        return defaultValue;
    }

    private boolean printAuthenticationException() {
        AuthenticationException authenticationException = loginParameters.getAuthenticationException();
        if (authenticationException == null) {
            return false;
        }
        String errorMessageKey = authenticationException.getErrorMessageKey();
        if ((!errorMessageKey.equals(AuthenticationException.UNDEFINED_ERROR)) && (!errorMessageKey.equals(AuthenticationException.EXIT_ERROR))) {
            this
                    .P("login-Text login-Warning")
                    .__localize(errorMessageKey)
                    ._P();
            return true;
        } else {
            return false;
        }
    }

    private boolean printCurrentParameters() {
        RequestMap bdfRequestMap = loginParameters.getRequestMap();
        if (bdfRequestMap == null) {
            return false;
        }
        Set<String> paramNameSet = bdfRequestMap.getParameterNameSet();
        HtmlAttributes hiddenAttr = HA.type(HtmlConstants.HIDDEN_TYPE);
        for (String paramName : paramNameSet) {
            if (!paramName.startsWith("bdf-")) {
                String[] paramValues = bdfRequestMap.getParameterValues(paramName);
                if (paramValues != null) {
                    int length = paramValues.length;
                    if (length == 1) {
                        this
                                .INPUT(hiddenAttr.name(paramName).value(paramValues[0]), true);
                    } else {
                        for (int i = 0; i < length; i++) {
                            this
                                    .INPUT(hiddenAttr.name(paramName).value(paramValues[i]), false);
                        }
                    }
                }
            }
        }
        return true;
    }

    private List<Sphere> checkSphereList() {
        List<Sphere> result = new ArrayList<Sphere>();
        List<SubsetKey> customSphereKeyList = loginParameters.getLoginSphrereKeyList();
        if (customSphereKeyList != null) {
            for (SubsetKey sphereKey : customSphereKeyList) {
                Sphere sphere = (Sphere) fichotheque.getSubset(sphereKey);
                if (sphere != null) {
                    result.add(sphere);
                }
            }
            if (!result.isEmpty()) {
                return result;
            }
        }
        List<SubsetKey> sphereKeyList = TreeUtils.toList(bdfServer.getTreeManager().getSubsetTree(SubsetKey.CATEGORY_SPHERE));
        for (SubsetKey sphereKey : sphereKeyList) {
            Sphere sphere = (Sphere) fichotheque.getSubset(sphereKey);
            if (sphere != null) {
                if (!BdfSessionSpace.isHiddenAtLogin(sphere)) {
                    result.add(sphere);
                }
            }
        }
        return result;
    }

    private String getTitle() {
        FichothequeMetadata fichothequeMetadata = bdfServer.getFichotheque().getFichothequeMetadata();
        String phraseName = loginParameters.getTitlePhraseName();
        if (phraseName != null) {
            Phrase fichothequePhrase = fichothequeMetadata.getPhrases().getPhrase(phraseName);
            if (fichothequePhrase != null) {
                Label label = fichothequePhrase.getLangPartCheckedLabel(workingLang);
                if (label != null) {
                    return label.getLabelString();
                }
            }
        }
        return FichothequeMetadataUtils.getLongTitle(bdfServer.getFichotheque(), workingLang);
    }


}
