/* BDF - Copyright (c) 2021-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.servlets;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.instruction.BdfInstruction;
import fr.exemole.bdfserver.api.interaction.Domains;
import fr.exemole.bdfserver.api.session.LoginException;
import fr.exemole.bdfserver.api.session.LoginParameters;
import fr.exemole.bdfserver.html.LoginHtmlProducer;
import fr.exemole.bdfserver.jsonproducers.session.PingJsonProducer;
import fr.exemole.bdfserver.tools.instruction.BdfInstructionUtils;
import fr.exemole.bdfserver.tools.session.LoginParametersBuilder;
import java.text.ParseException;
import net.fichotheque.SubsetKey;
import net.mapeadores.util.html.HtmlProducer;
import net.mapeadores.util.localisation.LangPreference;
import net.mapeadores.util.localisation.MessageLocalisation;
import net.mapeadores.util.logging.CommandMessage;
import net.mapeadores.util.logging.LogUtils;
import net.mapeadores.util.request.RequestConstants;
import net.mapeadores.util.request.RequestMap;
import net.mapeadores.util.request.RequestUtils;
import net.mapeadores.util.servlets.ResponseHandler;
import net.mapeadores.util.servlets.handlers.HtmlResponseHandler;
import net.mapeadores.util.servlets.handlers.JsonResponseHandler;
import net.mapeadores.util.text.StringUtils;


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

    private LoginEngine() {

    }

    public static ResponseHandler resolveLoginException(BdfServer bdfServer, RequestMap requestMap, String pathInfo, BdfInstruction bdfInstruction, LoginException loginException) {
        if ((BdfInstructionUtils.isJsonOutput(bdfInstruction)) || (RequestUtils.isJsonDefined(requestMap))) {
            return getJsonResponseHandler(bdfServer, requestMap, loginException);
        } else {
            return HtmlResponseHandler.init(getHtmlProducer(bdfServer, requestMap, pathInfo, bdfInstruction, loginException));
        }
    }

    private static JsonResponseHandler getJsonResponseHandler(BdfServer bdfServer, RequestMap requestMap, LoginException loginException) {
        LangPreference langPreference = BdfInstructionUtils.getLangPreference(requestMap, bdfServer);
        MessageLocalisation messageLocalisation = bdfServer.getL10nManager().getMessageLocalisation(langPreference);
        PingJsonProducer jsonProducer = PingJsonProducer.unauthentified(messageLocalisation, LogUtils.error(loginException.getErrorMessageKey()));
        return JsonResponseHandler.build(jsonProducer, requestMap).giveAccess(requestMap);
    }

    private static HtmlProducer getHtmlProducer(BdfServer bdfServer, RequestMap requestMap, String pathInfo, BdfInstruction bdfInstruction, LoginException loginException) {
        HtmlProducer customHtmlProducer = (HtmlProducer) bdfInstruction.getLoginOption(BdfInstruction.HTMLPRODUCER_OPTION);
        if (customHtmlProducer != null) {
            return customHtmlProducer;
        }
        LangPreference langPreference = BdfInstructionUtils.getLangPreference(requestMap, bdfServer);
        LoginParameters loginParameters = (LoginParameters) bdfInstruction.getLoginOption(BdfInstruction.LOGINPARAMETERS_OPTION);
        if (loginParameters == null) {
            loginParameters = buildLoginParameters(requestMap, pathInfo, bdfInstruction, loginException);
        }
        return new LoginHtmlProducer(bdfServer, langPreference, loginParameters);
    }

    private static LoginParameters buildLoginParameters(RequestMap requestMap, String pathInfo, BdfInstruction bdfInstruction, LoginException loginException) {
        String formAction;
        int idx = pathInfo.lastIndexOf('/');
        if (idx == -1) {
            formAction = pathInfo.toLowerCase();
        } else {
            formAction = pathInfo.substring(idx + 1).toLowerCase();
        }
        if (formAction.length() == 0) {
            formAction = ".";
        }
        CommandMessage sessionMessage = getSessionMessage(bdfInstruction, loginException, formAction, requestMap);
        if (!formAction.equals(".")) {
            formAction = "./" + formAction;
        }
        SubsetKey defaultSphereKey = getDefaultSphereKey(bdfInstruction);
        LoginParametersBuilder builder = LoginParametersBuilder.init()
                .setFormAction(formAction)
                .setReversePath(StringUtils.getReversePath(pathInfo))
                .setLoginException(loginException)
                .setRequestMap(requestMap)
                .setCommandMessage(sessionMessage)
                .setTitlePhraseName((String) bdfInstruction.getLoginOption(BdfInstruction.TITLEPHRASENAME_OPTION))
                .setDefaultSphereKey(defaultSphereKey);
        populateAvailableSpheres(builder, bdfInstruction);
        return builder.toLoginParameters();
    }

    private static CommandMessage getSessionMessage(BdfInstruction bdfInstruction, LoginException loginException, String formAction, RequestMap requestMap) {
        CommandMessage sessionMessage = (CommandMessage) bdfInstruction.getLoginOption(BdfInstruction.SESSIONMESSAGE_OPTION);
        if (sessionMessage != null) {
            return sessionMessage;
        }
        if (loginException.getErrorMessageKey().equals(LoginException.EXIT_ERROR)) {
            return LogUtils.done("_ info.session.newsession");
        } else {
            if ((formAction.equals(".")) || (formAction.equals(Domains.SESSION)) || (formAction.equals("index.html")) || (formAction.startsWith("app-"))) {
                return LogUtils.done("_ info.session.newsession");
            } else if (formAction.indexOf('.') != -1) {
                return LogUtils.done("_ warning.session.protectedcontent");
            } else {
                if (requestMap.getParameter(RequestConstants.COMMAND_PARAMETER) != null) {
                    return LogUtils.done("_ warning.session.expiredsession");
                } else {
                    return LogUtils.done("_ info.session.newsession");
                }
            }
        }
    }

    private static SubsetKey getDefaultSphereKey(BdfInstruction bdfInstruction) {
        SubsetKey defaultSphereKey = null;
        Object defaultSphereObj = (String) bdfInstruction.getLoginOption(BdfInstruction.DEFAULTSPHERE_OPTION);
        if (defaultSphereObj != null) {
            if (defaultSphereObj instanceof String) {
                try {
                    defaultSphereKey = SubsetKey.parse(SubsetKey.CATEGORY_SPHERE, (String) defaultSphereObj);
                } catch (ParseException pe) {

                }
            } else if (defaultSphereObj instanceof SubsetKey) {
                defaultSphereKey = (SubsetKey) defaultSphereObj;
                if (!defaultSphereKey.isSphereSubset()) {
                    defaultSphereKey = null;
                }
            }
        }
        return defaultSphereKey;
    }

    private static LoginParametersBuilder populateAvailableSpheres(LoginParametersBuilder builder, BdfInstruction bdfInstruction) {
        Object obj = bdfInstruction.getLoginOption(BdfInstruction.AVAILABLESPHERES_OPTION);
        if (obj != null) {
            if (obj instanceof String[]) {
                String[] array = (String[]) obj;
                for (String name : array) {
                    try {
                        builder.addLoginSphereKey(name);
                    } catch (ParseException pe) {

                    }
                }
            }
        }
        return builder;
    }

}
