/* BdfServer_Multi - Copyright (c) 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.multi.subscribe;

import fr.exemole.bdfserver.multi.api.Multi;
import net.mapeadores.util.html.HtmlProducer;
import net.mapeadores.util.localisation.MessageLocalisation;
import net.mapeadores.util.logging.CommandMessage;
import net.mapeadores.util.logging.ErrorMessageException;
import net.mapeadores.util.logging.LogUtils;
import net.mapeadores.util.request.OutputInfo;
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.ResponseHandlerFactory;


/**
 *
 * @author Vincent Calame
 */
public class SubscribeEngine {

    private final static CommandMessage TEST_DONE_MESSAGE = LogUtils.done("_ done.global.test");
    private final SubscribeParameters subscribeParameters;
    private final Multi multi;
    private final RequestMap requestMap;
    private final OutputInfo outputInfo;


    private SubscribeEngine(SubscribeParameters subscribeParameters, OutputInfo outputInfo) {
        this.subscribeParameters = subscribeParameters;
        this.outputInfo = outputInfo;
        this.multi = subscribeParameters.multi();
        this.requestMap = subscribeParameters.requestMap();
    }

    private ResponseHandler run() throws ErrorMessageException {
        SubscribeCommand subscribeCommand = getCommand();
        if (subscribeCommand != null) {
            if (requestMap.isTrue(RequestConstants.TEST_PARAMETER)) {
                return testCommand(subscribeCommand);
            } else {
                SubscribeResult subscribeResult = subscribeCommand.doSubscribeCommand();
                return HtmlResponseHandler.init(new SubscribeMessageHtmlProducer(multi, subscribeResult));
            }
        } else {
            switch (outputInfo.getType()) {
                case OutputInfo.JSON_TYPE:
                default: {
                    HtmlProducer htmlProducer = getNoCommandHtmlProducer();
                    return HtmlResponseHandler.init(htmlProducer);
                }
            }
        }
    }

    private HtmlProducer getNoCommandHtmlProducer() throws ErrorMessageException {
        String token = requestMap.getParameter(SubscribeCommand.TOKEN_PARAMNAME);
        if (token != null) {
            SubscribeToken subscribeToken = SubscribeCommand.getValidToken(subscribeParameters, token);
            return new FichothequeFormHtmlProducer(multi, subscribeToken);
        } else {
            return new AskFormHtmlProducer(multi);
        }
    }

    private ResponseHandler testCommand(SubscribeCommand subscribeCommand) {
        CommandMessage commandMessage;
        try {
            subscribeCommand.testCommand();
            commandMessage = TEST_DONE_MESSAGE;
        } catch (ErrorMessageException eme) {
            commandMessage = eme.getErrorMessage();
        }
        if (RequestUtils.isJsonDefined(requestMap)) {
            MessageLocalisation messageLocalisation = multi.getAdminMessageLocalisation();
            return ResponseHandlerFactory.getJsonInstance(messageLocalisation, requestMap, commandMessage);
        } else {
            return HtmlResponseHandler.init(new SubscribeMessageHtmlProducer(subscribeParameters.multi(), commandMessage));
        }
    }

    public static ResponseHandler run(SubscribeParameters subscribeParameters, OutputInfo outputInfo) {
        SubscribeEngine subscribeEngine = new SubscribeEngine(subscribeParameters, outputInfo);
        try {
            return subscribeEngine.run();
        } catch (ErrorMessageException eme) {
            return HtmlResponseHandler.init(new SubscribeMessageHtmlProducer(subscribeParameters.multi(), eme.getErrorMessage()));
        }
    }


    private SubscribeCommand getCommand() throws ErrorMessageException {
        String cmd = subscribeParameters.requestMap().getParameter(RequestConstants.COMMAND_PARAMETER);
        if (cmd == null) {
            return null;
        }
        SubscribeCommand command = getCommand(cmd);
        if (command == null) {
            throw new ErrorMessageException("_ error.unknown.parametervalue", "cmd", cmd);
        } else {
            return command;
        }
    }

    private SubscribeCommand getCommand(String commandName) throws ErrorMessageException {
        switch (commandName) {
            case AskForTokenCommand.COMMAND_NAME:
                return new AskForTokenCommand(subscribeParameters);
            case FichothequeSubscribeCommand.COMMAND_NAME:
                String token = requestMap.getParameter(SubscribeCommand.TOKEN_PARAMNAME);
                return new FichothequeSubscribeCommand(subscribeParameters);
            default:
                return null;
        }
    }

    private SubscribeToken getValidToken(String token) throws ErrorMessageException {
        SubscribeToken subscribeToken = subscribeParameters.subscribeManager().getSubcribeToken(token);
        if (subscribeToken == null) {
            throw new ErrorMessageException("_ error.unknown.subscribe.token", token);
        }
        if (subscribeToken.isExpired()) {
            throw new ErrorMessageException("_ error.unsupported.subscribe.token", token);
        }
        if (subscribeToken.isUsed()) {
            throw new ErrorMessageException("_ error.existing.subscribe.token", token);
        }
        return subscribeToken;
    }

}
