/* BdfServer_JsonProducers - Copyright (c) 2017-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.jsonproducers.corpus;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.ficheform.FormEntry;
import fr.exemole.bdfserver.api.ficheform.FormEntryProvider;
import fr.exemole.bdfserver.api.instruction.OutputParameters;
import fr.exemole.bdfserver.api.interaction.domains.CorpusDomain;
import fr.exemole.bdfserver.api.ui.FieldUi;
import fr.exemole.bdfserver.api.ui.IncludeUi;
import fr.exemole.bdfserver.api.ui.UiComponent;
import fr.exemole.bdfserver.tools.BdfServerUtils;
import fr.exemole.bdfserver.tools.ficheform.FormEntryProviderFactory;
import fr.exemole.bdfserver.tools.instruction.BdfInstructionUtils;
import fr.exemole.bdfserver.tools.instruction.OutputRequestHandler;
import fr.exemole.bdfserver.tools.instruction.ResultJsonProducer;
import fr.exemole.bdfserver.tools.interaction.PropertiesParam;
import fr.exemole.bdfserver.tools.subsettree.TreeUtils;
import java.util.ArrayList;
import java.util.List;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.FicheMeta;
import net.fichotheque.corpus.Fiches;
import net.fichotheque.exportation.table.CellConverter;
import net.fichotheque.pointeurs.FichePointeur;
import net.fichotheque.selection.FicheSelector;
import net.fichotheque.selection.SelectionContext;
import net.fichotheque.thesaurus.Thesaurus;
import net.fichotheque.tools.corpus.FichesBuilder;
import net.fichotheque.tools.permission.PermissionUtils;
import net.fichotheque.utils.pointeurs.PointeurFactory;
import net.fichotheque.utils.selection.FicheSelectorBuilder;
import net.mapeadores.util.json.JsonProducer;
import net.mapeadores.util.json.JsonProperty;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.logging.ErrorMessageException;
import net.mapeadores.util.request.RequestMap;


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

    private CorpusJsonProducerFactory() {

    }

    public static JsonProducer getJsonProducer(OutputParameters parameters) throws ErrorMessageException {
        String json = parameters.getOutput();
        ResultJsonProducer jsonProducer = new ResultJsonProducer(parameters);
        JsonProperty jsonProperty = getJsonProperty(parameters, json);
        if (jsonProperty == null) {
            return null;
        } else {
            jsonProducer.add(jsonProperty);
            return jsonProducer;
        }
    }

    public static JsonProperty getJsonProperty(OutputParameters parameters, String name) throws ErrorMessageException {
        OutputRequestHandler requestHandler = OutputRequestHandler.init(parameters);
        BdfServer bdfServer = parameters.getBdfServer();
        Lang lang = parameters.getWorkingLang();
        switch (name) {
            case CorpusDomain.UI_JSON: {
                Corpus corpus = requestHandler.getCorpus();
                return new UiJsonProperty(corpus, lang, bdfServer.getUiManager().getMainUiComponents(corpus));
            }
            case CorpusDomain.REMOVEDLIST_JSON: {
                Corpus corpus = requestHandler.getCorpus();
                return new LastRevisionsProperty(bdfServer, corpus.getRemovedFicheHistoryList());
            }
            case CorpusDomain.JUNCTIONHISTORYLIST_JSON: {
                Corpus corpus = requestHandler.getCorpus();
                int id = requestHandler.getMandatoryId();
                Thesaurus thesaurus = requestHandler.getThesaurus();
                return new JunctionHistoryArrayProperty(corpus.getJunctionHistoryList(id, thesaurus.getSubsetKey()));
            }
            case CorpusDomain.FICHES_JSON: {
                Fiches fiches = getFiches(requestHandler);
                return new FichesJsonProperty(parameters.getPermissionSummary(), fiches, BdfInstructionUtils.getCellConverter(parameters), parameters.getWorkingLang());
            }
            case CorpusDomain.FICHE_JSON: {
                FicheMeta ficheMeta = requestHandler.getFicheMeta();
                parameters.checkRead(ficheMeta);
                return resolveJsonProperty(parameters, ficheMeta);
            }
            default:
                return null;
        }
    }

    private static Fiches getFiches(OutputRequestHandler requestHandler) throws ErrorMessageException {
        SelectionContext selectionContext = BdfServerUtils.initSelectionContextBuilder(requestHandler)
                .setSubsetAccessPredicate(requestHandler.getPermissionSummary().getSubsetAccessPredicate())
                .setFichePredicate(PermissionUtils.getFichePredicate(requestHandler.getPermissionSummary()))
                .toSelectionContext();
        FicheSelector ficheSelector = requestHandler.populate(FicheSelectorBuilder.init(selectionContext))
                .toFicheSelector();
        return FichesBuilder.init(requestHandler.getComparator(selectionContext.getWorkingLang()))
                .initSubsetKeyOrder(TreeUtils.getCorpusKeyList(requestHandler.getBdfServer()))
                .populate(ficheSelector)
                .toFiches();
    }

    private static JsonProperty resolveJsonProperty(OutputParameters parameters, FicheMeta ficheMeta) throws ErrorMessageException {
        RequestMap requestMap = parameters.getRequestMap();
        PropertiesParam propertiesParam = PropertiesParam.fromRequest(requestMap);
        CellConverter cellConverter = null;
        if (propertiesParam.isSpecial()) {
            switch (propertiesParam.getName()) {
                case PropertiesParam.FORM_SPECIAL:
                    return resolveFormSpecialJsonProperty(parameters, ficheMeta);
            }
        }
        cellConverter = BdfInstructionUtils.getCellConverter(parameters);
        return new FicheJsonProperty(parameters.getPermissionSummary(), ficheMeta, cellConverter);

    }

    private static JsonProperty resolveFormSpecialJsonProperty(OutputParameters parameters, FicheMeta ficheMeta) throws ErrorMessageException {
        FichePointeur fichePointeur = PointeurFactory.newFichePointeur(ficheMeta.getCorpus(), true).setCurrentFicheMeta(ficheMeta);
        FormEntryProvider formEntryProvider = FormEntryProviderFactory.newInstance(parameters);
        List<FormEntry> formEntryList = new ArrayList<FormEntry>();
        for (UiComponent uiComponent : parameters.getBdfServer().getUiManager().getMainUiComponents(ficheMeta.getCorpus()).getUiComponentList()) {
            if (uiComponent instanceof FieldUi) {
                FormEntry.Field formEntry = formEntryProvider.getFormEntry(fichePointeur, (FieldUi) uiComponent);
                if (formEntry != null) {
                    formEntryList.add(formEntry);
                }
            } else if (uiComponent instanceof IncludeUi) {
                FormEntry.Include formEntry = formEntryProvider.getFormEntry(fichePointeur, (IncludeUi) uiComponent);
                if (formEntry != null) {
                    formEntryList.add(formEntry);
                }
            }
        }
        return new FicheFormJsonProperty(parameters.getPermissionSummary(), ficheMeta, formEntryList, parameters.getWorkingLang());
    }

}
