/* BDF - Copyright (c) 2022-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.Domain;
import fr.exemole.bdfserver.api.interaction.Domains;
import fr.exemole.bdfserver.api.interaction.InteractionConstants;
import fr.exemole.bdfserver.api.session.LoginException;
import fr.exemole.bdfserver.conf.ConfConstants;
import fr.exemole.bdfserver.conf.ConfUtils;
import fr.exemole.bdfserver.get.GetInstructionFactory;
import fr.exemole.bdfserver.multi.api.Multi;
import fr.exemole.bdfserver.multi.api.central.CentralSphere;
import fr.exemole.bdfserver.multi.api.central.CentralUser;
import fr.exemole.bdfserver.multi.api.namespaces.IndexSpace;
import static fr.exemole.bdfserver.servlets.BDFWebapp.BDFSESSION_KEY;
import fr.exemole.bdfserver.servlets.instructions.AppInstruction;
import fr.exemole.bdfserver.servlets.instructions.DomainInstruction;
import fr.exemole.bdfserver.servlets.instructions.RunInstruction;
import fr.exemole.bdfserver.servlets.instructions.SessionInstruction;
import java.text.ParseException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import net.fichotheque.SubsetKey;
import net.fichotheque.sphere.LoginKey;
import net.fichotheque.sphere.Redacteur;
import net.fichotheque.utils.SphereUtils;
import net.mapeadores.util.attr.Attribute;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.LangPreference;
import net.mapeadores.util.localisation.LangPreferenceBuilder;
import net.mapeadores.util.request.RequestMap;
import net.mapeadores.util.request.RequestUtils;
import net.mapeadores.util.servlets.HttpServletRequestMap;


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

    private BDFUtils() {

    }

    public static boolean hasLogin(HttpServletRequestMap requestMap) {
        String bdfLogin = requestMap.getParameter(InteractionConstants.BDF_LOGIN_PARAMNAME);
        if (bdfLogin == null) {
            bdfLogin = requestMap.getParameter("bdf-idsphere"); //Ancienne version
        }
        return (bdfLogin != null);
    }

    public static LoginKey getLoginKey(HttpServletRequestMap requestMap) throws LoginException {
        String completeLogin = getCompleteLogin(requestMap);
        try {
            LoginKey loginKey = LoginKey.parse(completeLogin);
            return loginKey;
        } catch (ParseException pe) {
            throw new LoginException(LoginException.LOGIN_ERROR);
        }
    }

    public static CentralUser getCentralUser(HttpServletRequestMap requestMap, Multi multi) throws LoginException {
        LoginKey loginKey = BDFUtils.getLoginKey(requestMap);
        CentralSphere centralSphere = multi.getCentralSphere(loginKey.getSphereName());
        if (centralSphere == null) {
            throw new LoginException(LoginException.SPHERE_ERROR);
        }
        CentralUser centralUser = centralSphere.getCentralUser(loginKey.getLogin());
        if (centralUser == null) {
            throw new LoginException(LoginException.LOGIN_ERROR);
        } else {
            return centralUser;
        }
    }

    public static Redacteur getRedacteur(BdfServer bdfServer, HttpServletRequestMap requestMap) throws LoginException {
        String completeLogin = getCompleteLogin(requestMap);
        Redacteur redacteur;
        try {
            redacteur = SphereUtils.parse(bdfServer.getFichotheque(), completeLogin);
        } catch (SphereUtils.RedacteurLoginException rle) {
            if (rle.getType() == SphereUtils.UNKNOWN_SPHERE) {
                throw new LoginException(LoginException.SPHERE_ERROR);
            } else {
                throw new LoginException(LoginException.LOGIN_ERROR);
            }
        }
        if (redacteur == null) {
            throw new LoginException(LoginException.LOGIN_ERROR);
        }
        return redacteur;
    }

    public static String getCompleteLogin(HttpServletRequestMap requestMap) throws LoginException {
        String bdfLogin = requestMap.getParameter(InteractionConstants.BDF_LOGIN_PARAMNAME);
        if (bdfLogin == null) {
            bdfLogin = requestMap.getParameter("bdf-idsphere"); //Ancienne version
        }
        if (bdfLogin == null) {
            throw new LoginException(LoginException.UNDEFINED_ERROR);
        }
        String bdfSphere = requestMap.getParameter(InteractionConstants.BDF_SPHERE_PARAMNAME);
        bdfLogin = bdfLogin.trim();
        if (!bdfLogin.contains("[")) {
            if (bdfSphere != null) {
                bdfSphere = bdfSphere.trim();
            }
            if ((bdfSphere == null) || (bdfSphere.isEmpty())) {
                throw new LoginException(LoginException.SPHERE_ERROR);
            } else {
                bdfLogin = bdfLogin + "[" + bdfSphere + "]";
            }
        }
        return bdfLogin;
    }

    public static String getRootUrl(HttpServletRequest request, String fichothequeName) {
        StringBuilder url = new StringBuilder();
        String scheme = request.getScheme();
        int port = request.getServerPort();
        if (port < 0) {
            port = 80; // Work around java.net.URL bug
        }
        url.append(scheme);
        url.append("://");
        url.append(request.getServerName());
        if ((scheme.equals("http") && (port != 80))
                || (scheme.equals("https") && (port != 443))) {
            url.append(':');
            url.append(port);
        }
        url.append(request.getContextPath());
        url.append("/");
        if ((!fichothequeName.isEmpty()) && (!fichothequeName.equals(ConfConstants.UNIQUE_NAME))) {
            url.append(fichothequeName);
            url.append("/");
        }
        return url.toString();
    }

    public static BDFSession getCurrentBdfSession(HttpServletRequest request) {
        HttpSession session = request.getSession(false);
        if (session != null) {
            return (BDFSession) session.getAttribute(BDFSESSION_KEY);
        }
        return null;
    }

    public static Domain parsePathInfo(String pathInfo) {
        String firstPart = pathInfo.toLowerCase();
        String secondPart = "";
        int length = pathInfo.length();
        for (int i = 0; i < length; i++) {
            char carac = pathInfo.charAt(i);
            boolean isSeparator = false;
            switch (carac) {
                case ':':
                case '_':
                case '-':
                    isSeparator = true;
                    break;
            }
            if (isSeparator) {
                secondPart = firstPart.substring(i + 1);
                firstPart = firstPart.substring(0, i);
                break;
            }
        }
        return new Domain(firstPart, secondPart);
    }

    public static BdfInstruction getDomainBdfInstruction(BdfServer bdfServer, RequestMap requestMap, Domain domain) {
        switch (domain.getFirstPart()) {
            case Domains.SESSION:
                return new SessionInstruction(bdfServer, requestMap);
            case Domains.RUN:
                return new RunInstruction(bdfServer, requestMap);
            case Domains.APP:
                return AppInstruction.build(bdfServer, requestMap, domain.getSecondPart());
            case Domains.ADMINISTRATION:
            case Domains.ALBUM:
            case Domains.CONFIGURATION:
            case Domains.CORPUS:
            case Domains.MAILING:
            case Domains.EXPORTATION:
            case Domains.EDITION:
            case Domains.SELECTION:
            case Domains.SPHERE:
            case Domains.THESAURUS:
            case Domains.MAIN:
            case Domains.MISC:
            case Domains.ADDENDA:
            case Domains.IMPORTATION:
            case Domains.PIOCHE:
            case Domains.EXTENSION:
                return new DomainInstruction(bdfServer, requestMap, domain);
            default:
                return null;
        }
    }

    public static BdfInstruction getBdfInstruction(BdfServer bdfServer, RequestMap requestMap, String pathInfo) {
        int idx = pathInfo.indexOf('/');
        if (idx == -1) {
            Domain domain = BDFUtils.parsePathInfo(pathInfo);
            return BDFUtils.getDomainBdfInstruction(bdfServer, requestMap, domain);
        } else {
            String first = pathInfo.substring(0, idx);
            String next = pathInfo.substring(idx + 1);
            return GetInstructionFactory.getBdfInstruction(bdfServer, requestMap, first, next);
        }
    }

    public static LangPreference getLangPreference(Multi multi, HttpServletRequestMap requestMap) {
        return RequestUtils.checkLangPreference(requestMap, new LangPreferenceBuilder())
                .addLangs(multi.getMultiMetadata().getWorkingLangs())
                .addLang(Lang.build("fr"))
                .toLangPreference();
    }

    public static SubsetKey getValidCentralSphere(Multi multi, String sphereName) {
        try {
            SubsetKey sphereKey = SubsetKey.parse(SubsetKey.CATEGORY_SPHERE, sphereName);
            if (multi.getCentralSphereNameSet().contains(sphereKey.getSubsetName())) {
                return sphereKey;
            } else {
                return null;
            }
        } catch (ParseException pe) {
            return null;
        }

    }

    public static String getFichothequeRedirect(Multi multi) {
        String value = null;
        Attribute attribute = multi.getMultiMetadata().getAttributes().getAttribute(IndexSpace.REDIRECT_KEY);
        if (attribute != null) {
            value = attribute.getFirstValue();
        } else {
            value = multi.getMultiConf().getParam("default_fichotheque");
        }
        if (value != null) {
            if (!ConfUtils.isValidMultiName(value)) {
                value = null;
            }
        }
        return value;
    }

}
