/* BdfServer_Get - Copyright (c) 2023-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.get.instructions;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.instruction.BdfInstruction;
import fr.exemole.bdfserver.api.instruction.BdfInstructionConstants;
import fr.exemole.bdfserver.api.managers.AccessManager;
import fr.exemole.bdfserver.api.users.BdfUser;
import fr.exemole.bdfserver.get.access.v1.V1EndPointFactory;
import fr.exemole.bdfserver.tools.instruction.BdfErrors;
import fr.exemole.bdfserver.tools.instruction.BdfInstructionUtils;
import java.text.ParseException;
import net.fichotheque.exportation.access.AccessDef;
import net.mapeadores.util.json.JsonProducer;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.MessageLocalisation;
import net.mapeadores.util.logging.CommandMessageJsonProducer;
import net.mapeadores.util.logging.ErrorMessageException;
import net.mapeadores.util.request.RequestMap;
import net.mapeadores.util.servlets.ResponseHandler;
import net.mapeadores.util.servlets.handlers.JsonResponseHandler;
import net.mapeadores.util.text.RelativePath;


/**
 *
 * @author Vincent Calame
 */
public class AccessInstruction implements BdfInstruction {

    private final BdfServer bdfServer;
    private final RequestMap requestMap;
    private final int version;
    private final AccessDef accessDef;
    private final String endPoint;

    private AccessInstruction(BdfServer bdfServer, RequestMap requestMap, int version, AccessDef accessDef, String endPoint) {
        this.bdfServer = bdfServer;
        this.requestMap = requestMap;
        this.version = version;
        this.accessDef = accessDef;
        this.endPoint = endPoint;
    }

    @Override
    public short getBdfUserNeed() {
        switch (accessDef.getType()) {
            case AccessDef.PRIVATE_ACCESS:
                return BdfInstructionConstants.MANDATORY_BDFUSER;
            default:
                return BdfInstructionConstants.NONE_BDFUSER;
        }
    }

    @Override
    public ResponseHandler runInstruction(BdfUser bdfUser) {
        Lang lang = getLang(bdfUser);
        JsonProducer jsonProducer;
        try {
            checkToken();
            jsonProducer = V1EndPointFactory.getJsonProducer(bdfServer, requestMap, accessDef, lang, endPoint, bdfUser);
        } catch (ErrorMessageException eme) {
            MessageLocalisation messageLocalisation;
            if (bdfUser != null) {
                messageLocalisation = bdfServer.getL10nManager().getMessageLocalisation(bdfUser);
            } else {
                messageLocalisation = bdfServer.getL10nManager().getMessageLocalisation(lang);
            }
            jsonProducer = new CommandMessageJsonProducer(messageLocalisation, eme.getErrorMessage());
        }
        if (jsonProducer != null) {
            return JsonResponseHandler.build(jsonProducer, requestMap);
        } else {
            return null;
        }
    }

    private Lang getLang(BdfUser bdfUser) {
        String langValue = requestMap.getParameter("lang");
        if (langValue != null) {
            try {
                Lang lang = Lang.parse(langValue);
                return lang;
            } catch (ParseException pe) {

            }
        }
        if (bdfUser != null) {
            return bdfUser.getWorkingLang();
        } else {
            return bdfServer.getDefaultWorkingLang();
        }
    }

    private void checkToken() throws ErrorMessageException {
        if (!accessDef.getType().equals(AccessDef.TOKEN_ACCESS)) {
            return;
        }
        String validToken = accessDef.getToken();
        String currentToken = requestMap.getTrimedParameter("token");
        if (!currentToken.equals(validToken)) {
            throw BdfErrors.error("_ error.wrong.token", currentToken);
        }
    }


    public static BdfInstruction build(BdfServer bdfServer, RequestMap requestMap, String filePath) {
        BdfInstruction bdfInstruction = innerBuild(bdfServer, requestMap, filePath);
        if (bdfInstruction != null) {
            return bdfInstruction;
        } else {
            return BdfInstructionUtils.NOTFOUND_BDFINSTRUCTION;
        }
    }

    private static BdfInstruction innerBuild(BdfServer bdfServer, RequestMap requestMap, String filePath) {
        RelativePath relativePath;
        try {
            relativePath = RelativePath.parse(filePath);
        } catch (ParseException pe) {
            return null;
        }
        String[] pathArray = relativePath.toArray();
        if (pathArray.length < 3) {
            return null;
        }
        int version = getVersion(pathArray[0]);
        if (version < 0) {
            return null;
        }
        AccessManager accessManager = bdfServer.getAccessManager();
        AccessDef accessDef = accessManager.getAccessDef(pathArray[1]);
        if (accessDef == null) {
            return null;
        }
        String endPoint = pathArray[2];
        return new AccessInstruction(bdfServer, requestMap, version, accessDef, endPoint);
    }

    private static int getVersion(String part) {
        switch (part) {
            case "v1":
                return 1;
            default:
                return -1;
        }
    }

}
