/* BdfServer - Copyright (c) 2010-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.tools.instruction;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.exportation.table.FicheTableParameters;
import fr.exemole.bdfserver.api.instruction.BdfCommandParameters;
import fr.exemole.bdfserver.api.instruction.BdfCommandResult;
import fr.exemole.bdfserver.api.instruction.BdfInstruction;
import fr.exemole.bdfserver.api.instruction.BdfInstructionConstants;
import fr.exemole.bdfserver.api.instruction.OutputParameters;
import fr.exemole.bdfserver.api.instruction.TypedBdfInstruction;
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.users.BdfUser;
import fr.exemole.bdfserver.tools.configuration.ConfigurationUtils;
import fr.exemole.bdfserver.tools.exportation.table.BdfTableExportUtils;
import fr.exemole.bdfserver.tools.interaction.PropertiesParam;
import java.text.ParseException;
import net.fichotheque.Subset;
import net.fichotheque.SubsetItem;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.FicheMeta;
import net.fichotheque.exportation.table.CellConverter;
import net.fichotheque.extraction.ExtractionContext;
import net.fichotheque.utils.TableExportUtils;
import net.mapeadores.util.annotation.Nullable;
import net.mapeadores.util.json.JsonProducer;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.LangPreference;
import net.mapeadores.util.localisation.LangPreferenceBuilder;
import net.mapeadores.util.localisation.MessageLocalisation;
import net.mapeadores.util.localisation.UserLangContext;
import net.mapeadores.util.logging.CommandMessage;
import net.mapeadores.util.logging.CommandMessageJsonProducer;
import net.mapeadores.util.logging.ErrorMessageException;
import net.mapeadores.util.request.RequestMap;
import net.mapeadores.util.request.RequestUtils;
import net.mapeadores.util.servlets.ResponseHandler;


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

    public final static BdfInstruction NOTFOUND_BDFINSTRUCTION = new NotFoundBdfInstruction();


    private BdfInstructionUtils() {
    }

    public static MessageLocalisation getMessageLocalisation(RequestMap requestMap, BdfServer bdfServer, @Nullable UserLangContext userLangContext) {
        if (userLangContext != null) {
            return bdfServer.getL10nManager().getMessageLocalisation(userLangContext);
        } else {
            return bdfServer.getL10nManager().getMessageLocalisation(getLangPreference(requestMap, bdfServer));
        }
    }

    public static LangPreference getLangPreference(RequestMap requestMap, BdfServer bdfServer) {
        LangPreferenceBuilder langPreferenceBuilder = new LangPreferenceBuilder();
        RequestUtils.checkLangPreference(requestMap, langPreferenceBuilder);
        ConfigurationUtils.checkLangPreference(bdfServer.getLangConfiguration(), langPreferenceBuilder);
        return langPreferenceBuilder
                .addLang(Lang.build("fr"))
                .toLangPreference();
    }

    public static SubsetItem checkMasterSubsetItem(Corpus corpus, int id, BdfUser bdfUser) throws ErrorMessageException {
        Subset masterSubset = corpus.getMasterSubset();
        if (masterSubset != null) {
            SubsetItem masterSubsetItem = masterSubset.getSubsetItemById(id);
            if (masterSubsetItem == null) {
                throw BdfErrors.error("_ error.unknown.mastersubsetitem", id, masterSubset.getSubsetKeyString());
            }
            return masterSubsetItem;
        } else {
            return null;
        }
    }

    public static boolean checkConfirmation(RequestMap requestMap, BdfServer bdfServer) {
        String checkConfirmation = requestMap.getParameter(InteractionConstants.CONFIRMATIONCHECK_PARAMNAME);
        if (checkConfirmation == null) {
            return false;
        }
        return (checkConfirmation.equals(InteractionConstants.OK_CONFIRMATIONCHECK_PARAMVALUE));
    }

    public static String getFicheGetLink(FicheMeta ficheMeta, String extension) {
        return "fiches/" + ficheMeta.getSubsetName() + "-" + String.valueOf(ficheMeta.getId()) + "." + extension;
    }

    public static String getFicheGetLink(FicheMeta ficheMeta, String extension, String name) {
        return "fiches/" + ficheMeta.getSubsetName() + "-" + String.valueOf(ficheMeta.getId()) + "-" + name + "." + extension;
    }

    public static String getCompilationGetLink(String extension) {
        return "fiches/compilation." + extension;
    }

    public static String getCompilationGetLink(String extension, String name) {
        return "fiches/_compilation-" + name + "." + extension;
    }

    public static String getExtensionDomain(String registrationName) {
        return Domain.getCompleteDomain(Domains.EXTENSION, registrationName);
    }

    public static boolean ownsToExtension(BdfCommandParameters bdfCommandParameters, String registrationName) {
        return isExtensionDomain(bdfCommandParameters.getDomain(), registrationName);
    }

    public static boolean ownsToExtension(OutputParameters parameters, String registrationName) {
        return isExtensionDomain(parameters.getDomain(), registrationName);
    }

    public static boolean isExtensionDomain(Domain domain, String registrationName) {
        return (domain.getFirstPart().equals(Domains.EXTENSION)) && (domain.getSecondPart().equals(registrationName));
    }

    public static String getAbsolutePageName(String domain, String page) {
        return domain + ":" + page;
    }

    public static String getAbsoluteCommandName(String domain, String commandName) {
        return domain + ":" + commandName;
    }

    public static String getPageOutput(String pageName) {
        return "page|" + pageName;
    }

    public static String getStreamOutput(String streamName) {
        return "stream|" + streamName;
    }

    public static String getJsonOutput(String jsonName) {
        return "json|" + jsonName;
    }

    public static boolean isJsonOutput(BdfInstruction bdfInstruction) {
        if (bdfInstruction instanceof TypedBdfInstruction) {
            return (((TypedBdfInstruction) bdfInstruction).getOutputType() == TypedBdfInstruction.JSON_TYPE);
        }
        return false;
    }

    public static String getPhraseParamPrefix(String phraseName) {
        return "phrase_" + phraseName + "/";
    }

    public static CellConverter getCellConverter(OutputParameters outputParameters) {
        return getCellConverter(outputParameters, false);
    }

    public static CellConverter getCellConverter(OutputParameters outputParameters, boolean noDefault) {
        BdfServer bdfServer = outputParameters.getBdfServer();
        PropertiesParam propertiesParam = PropertiesParam.fromRequest(outputParameters.getRequestMap());
        CellConverter cellConverter = null;
        switch (propertiesParam.getType()) {
            case PropertiesParam.SPECIAL_TYPE:
                switch (propertiesParam.getName()) {
                    case PropertiesParam.PHRASES_SPECIAL:
                        cellConverter = TableExportUtils.getPhraseConverter(outputParameters.getWorkingLang(), outputParameters.getFormatLocale());
                        break;
                    case PropertiesParam.TABLE_SPECIAL: {
                        OutputRequestHandler outputRequestHandler = new OutputRequestHandler(outputParameters);
                        Corpus corpus = getOptionalCorpus(outputRequestHandler);
                        String patternMode = getPatternMode(outputRequestHandler);
                        SubsetKey contextCorpusKey = null;
                        try {
                            contextCorpusKey = SubsetKey.parse(SubsetKey.CATEGORY_CORPUS, outputRequestHandler.getParameter("contextcorpus", false));
                        } catch (ParseException | ErrorMessageException e) {

                        }
                        cellConverter = BdfTableExportUtils.getSpecialTableCellConverter(outputParameters, contextCorpusKey, patternMode, corpus);
                        break;
                    }
                }
                break;
            case PropertiesParam.TABLEEXPORT_TYPE:
                ExtractionContext extractionContext = outputParameters.getDefaultExtractionContext();
                cellConverter = BdfTableExportUtils.getCellConverterFromName(bdfServer, extractionContext, propertiesParam.getName());
                break;
            case PropertiesParam.COMPONENTS_TYPE:
                OutputRequestHandler outputRequestHandler = new OutputRequestHandler(outputParameters);
                Corpus corpus = getOptionalCorpus(outputRequestHandler);
                String patternMode = getPatternMode(outputRequestHandler);
                cellConverter = BdfTableExportUtils.getComponentsCellConverter(outputParameters, propertiesParam.getComponentNameList(), patternMode, corpus);
                break;
        }
        if (cellConverter == null) {
            if (!noDefault) {
                cellConverter = TableExportUtils.EMPTY_CELLCONVERTER;
            }
        }
        return cellConverter;
    }

    private static Corpus getOptionalCorpus(OutputRequestHandler outputRequestHandler) {
        try {
            return outputRequestHandler.getMandatoryCorpus();
        } catch (ErrorMessageException eme) {
            return null;
        }
    }

    private static String getPatternMode(OutputRequestHandler outputRequestHandler) {
        String patternMode = outputRequestHandler.getTrimedParameter("patternmode");
        if (patternMode.isEmpty()) {
            return FicheTableParameters.LABEL_PATTERNMODE;
        }
        try {
            return FicheTableParameters.checkPatternMode(patternMode);
        } catch (IllegalArgumentException iae) {
            return FicheTableParameters.LABEL_PATTERNMODE;
        }
    }

    public static JsonProducer getDefaultJsonProducer(MessageLocalisation messageLocalisation, BdfCommandResult bdfCommandResult, CommandMessage errorMessage) {
        if ((bdfCommandResult != null) && (errorMessage != null)) {
            CommandMessage mainCommandMessage = bdfCommandResult.getCommandMessage();
            if (mainCommandMessage != null) {
                return new CommandMessageJsonProducer(messageLocalisation, mainCommandMessage, errorMessage);
            } else {
                return new CommandMessageJsonProducer(messageLocalisation, errorMessage);
            }
        } else if (bdfCommandResult != null) {
            return new ResultJsonProducer(bdfCommandResult, messageLocalisation);
        } else {
            return new CommandMessageJsonProducer(messageLocalisation, errorMessage);
        }
    }


    private static class NotFoundBdfInstruction implements BdfInstruction {

        private NotFoundBdfInstruction() {

        }

        @Override
        public short getBdfUserNeed() {
            return BdfInstructionConstants.NONE_BDFUSER;
        }

        @Override
        public ResponseHandler runInstruction(BdfUser bdfUser) {
            return null;
        }

    }

}
