/* BdfServer - Copyright (c) 2010-2024 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.balayage.engine.runners;

import fr.exemole.bdfserver.tools.balayage.BdfBalayageUtils;
import fr.exemole.bdfserver.tools.balayage.engine.BalayageLog;
import fr.exemole.bdfserver.tools.balayage.engine.BalayageParameters;
import fr.exemole.bdfserver.tools.configuration.ConfigurationUtils;
import java.io.File;
import java.util.function.Predicate;
import net.fichotheque.addenda.Addenda;
import net.fichotheque.corpus.FicheMeta;
import net.fichotheque.corpus.Fiches;
import net.fichotheque.corpus.SortConstants;
import net.fichotheque.exportation.balayage.BalayageUnit;
import net.fichotheque.selection.DocumentQuery;
import net.fichotheque.selection.FicheQuery;
import net.fichotheque.selection.FicheSelector;
import net.fichotheque.selection.SelectionContext;
import net.fichotheque.tools.corpus.FichesBuilder;
import net.fichotheque.tools.exportation.file.FileExportEngine;
import net.fichotheque.utils.SelectionUtils;
import net.fichotheque.utils.selection.FicheSelectorBuilder;
import net.fichotheque.utils.selection.SelectionContextBuilder;
import net.mapeadores.util.localisation.Message;
import net.mapeadores.util.logging.MessageHandler;
import net.mapeadores.util.text.AccoladePattern;
import net.fichotheque.exportation.balayage.BalayageOutput;


/**
 *
 * @author Vincent Calame
 */
public class DocumentBalayageUnitRunner extends AbstractBalayageUnitRunner {

    private final Predicate<String> extensionPredicate;
    private final boolean empty;
    private FileExportMessageHandler messageHandler;
    private File destinationDir;

    public DocumentBalayageUnitRunner(BalayageParameters balayageParameters, int balayageIndex, BalayageUnit balayageUnit) {
        super(balayageParameters, balayageIndex, balayageUnit);
        extensionPredicate = BdfBalayageUtils.getExtensionPredicate(balayageUnit);
        empty = (balayageUnit.getOutputList().isEmpty());
        if (!empty) {
            BalayageOutput output = balayageUnit.getOutputList().get(0);
            messageHandler = new FileExportMessageHandler(balayageIndex, balayageParameters.getBalayageLog(), output);
            File rootDirectory;
            if (output.isIncludeOutput()) {
                rootDirectory = ConfigurationUtils.getBalayageIncludeDirectory(balayageParameters.getBdfServer());
            } else {
                rootDirectory = balayageParameters.getBalayageRootDirectory();
            }
            destinationDir = rootDirectory;
            AccoladePattern pattern = output.getOutputPath();
            if (pattern != null) {
                destinationDir = new File(rootDirectory, pattern.toString());
            }
        }
    }

    @Override
    protected void run(String balayageUnitType) {
        if (empty) {
            return;
        }
        DocumentQuery documentQuery = balayageUnit.getDocumentQuery();
        Addenda[] addendaArray = SelectionUtils.toAddendaArray(extractionContext.getFichotheque(), documentQuery, extractionContext.getSubsetAccessPredicate());
        Predicate<FicheMeta> fichePredicate = balayageParameters.getSelectedFiches();
        FicheQuery ficheQuery = balayageUnit.getFicheQuery();
        boolean globalSelect = balayageUnit.isGlobalSelect();
        if (((!globalSelect) || (fichePredicate == null)) && (ficheQuery.isEmpty())) {
            FileExportEngine.run(destinationDir, addendaArray, extensionPredicate, messageHandler);
        } else {
            if (!globalSelect) {
                fichePredicate = null;
            }
            SelectionContext selectionContext = SelectionContextBuilder.build(extractionContext, defaultWorkingLang)
                    .setSubsetAccessPredicate(extractionContext.getSubsetAccessPredicate())
                    .setFichePredicate(fichePredicate)
                    .toSelectionContext();
            FicheSelector ficheSelector = FicheSelectorBuilder.init(selectionContext).add(ficheQuery).toFicheSelector();
            Fiches fiches = FichesBuilder.build(SortConstants.ID_ASC)
                    .populate(ficheSelector)
                    .toFiches();
            FileExportEngine.run(destinationDir, addendaArray, extensionPredicate, messageHandler, fiches);
        }
    }

    @Override
    public void dispose() {
        super.dispose();
    }

    @Override
    protected boolean isEmpty() {
        return empty;
    }


    private static class FileExportMessageHandler implements MessageHandler {

        private final BalayageLog balayageLog;
        private final int balayageIndex;
        private final BalayageOutput output;

        private FileExportMessageHandler(int balayageIndex, BalayageLog balayageLog, BalayageOutput output) {
            this.balayageIndex = balayageIndex;
            this.balayageLog = balayageLog;
            this.output = output;
        }

        @Override
        public void addMessage(String category, Message message) {
            if (category.startsWith("severe")) {
                balayageLog.addOutputError(balayageIndex, 0, output, BalayageLog.IO_EXCEPTION, message.getMessageKey(), "");
            } else if (message.getMessageKey().equals("_ info.file")) {
                balayageLog.addFileGeneration(balayageIndex, 0, (File) message.getMessageValues()[0]);
            }
        }

    }

}
