/* BdfServer - Copyright (c) 2011-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.runners;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.configuration.PathConfiguration;
import fr.exemole.bdfserver.api.exportation.sql.BdfServerSqlExport;
import fr.exemole.bdfserver.api.externalscript.ExternalScript;
import fr.exemole.bdfserver.tools.BdfServerUtils;
import fr.exemole.bdfserver.tools.configuration.ConfigurationUtils;
import fr.exemole.bdfserver.tools.configuration.Target;
import fr.exemole.bdfserver.tools.exportation.table.BdfTableExportUtils;
import fr.exemole.bdfserver.tools.exportation.table.CellConversionInit;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.function.Predicate;
import net.fichotheque.SubsetItem;
import net.fichotheque.exportation.sql.SqlExport;
import net.fichotheque.exportation.sql.SqlExportDef;
import net.fichotheque.exportation.table.CellConverter;
import net.fichotheque.exportation.table.TableExport;
import net.fichotheque.exportation.table.TableExportContext;
import net.fichotheque.extraction.ExtractionContext;
import net.fichotheque.permission.PermissionSummary;
import net.fichotheque.selection.FichothequeQueries;
import net.fichotheque.tools.exportation.sql.DefaultSqlExport;
import net.fichotheque.tools.permission.PermissionUtils;
import net.mapeadores.util.localisation.LangContext;
import net.mapeadores.util.logging.CommandMessage;
import net.mapeadores.util.logging.LogUtils;


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

    private SqlExportRunner() {

    }

    @SuppressWarnings("unchecked")
    public static CommandMessage run(SqlExportDef sqlExportDef, BdfServer bdfServer, PathConfiguration pathConfiguration, boolean runExternalScript) throws IOException {
        PermissionSummary permissionSummary = PermissionUtils.FICHOTHEQUEADMIN_PERMISSIONSUMMARY;
        String className = sqlExportDef.getSqlExportClassName();
        SqlExport sqlExport;
        if (className.isEmpty()) {
            sqlExport = new DefaultSqlExport();
        } else {
            try {
                Class classe = Class.forName(className);
                sqlExport = (SqlExport) classe.getDeclaredConstructor().newInstance();
            } catch (ClassNotFoundException cnfe) {
                return LogUtils.error("_ error.exception.classnotfound", className);
            } catch (IllegalAccessException iae) {
                return LogUtils.error("_ error.exception.illegalaccess", className);
            } catch (InstantiationException ie) {
                return LogUtils.error("_ error.exception.instantiation", className);
            } catch (ClassCastException cce) {
                return LogUtils.error("_ error.exception.classcast", className, "SqlExport");
            } catch (ReflectiveOperationException roe) {
                return LogUtils.error("_ error.exception.instantiation", className);
            }
        }
        TableExport tableExport = null;
        String tableExportName = sqlExportDef.getTableExportName();
        if (!tableExportName.isEmpty()) {
            tableExport = bdfServer.getTableExportManager().getTableExport(tableExportName);
        }
        LangContext langContext = null;
        if (tableExport == null) {
            tableExport = BdfTableExportUtils.toDefaultTableExport(bdfServer, BdfTableExportUtils.NONE_FICHETABLEPARAMETERS, permissionSummary);
        } else {
            langContext = BdfServerUtils.checkLangMode(bdfServer, tableExport.getTableExportDef());
        }
        if (langContext == null) {
            langContext = bdfServer.getLangConfiguration().toLangContext();
        }
        Predicate<SubsetItem> globalPredicate = initPredicate(bdfServer, permissionSummary, sqlExportDef);
        ExtractionContext extractionContext = BdfServerUtils.initExtractionContextBuilder(bdfServer, langContext, permissionSummary).toExtractionContext();
        CellConverter cellConverter = CellConversionInit.tableExport(bdfServer, extractionContext, tableExport, globalPredicate, false).getCellConverter();
        sqlExport.setExtractionContext(extractionContext);
        TableExportContext tableExportContext = bdfServer.getTableExportContext();
        sqlExport.setTableExport(tableExport, tableExportContext);
        sqlExport.setCellConverter(cellConverter);
        sqlExport.setPredicate(globalPredicate);
        for (SqlExportDef.Param param : sqlExportDef.getParamList()) {
            sqlExport.setParameter(param.getName(), param.getValue());
        }
        Target target = ConfigurationUtils.getTarget(pathConfiguration, sqlExportDef);
        if (sqlExport instanceof BdfServerSqlExport) {
            ((BdfServerSqlExport) sqlExport).setBdfServer(bdfServer);
        }
        try (OutputStream os = new FileOutputStream(target.getFile())) {
            sqlExport.exportDump(os);
        }
        if (runExternalScript) {
            ExternalScript externalScript = bdfServer.getExternalScriptManager().getExternalScript(sqlExportDef.getPostCommand());
            if (externalScript != null) {
                try {
                    externalScript.exec();
                } catch (IOException ioe) {
                }
            }
        }
        return LogUtils.done("_ done.exportation.sqlexportrun");
    }

    private static Predicate<SubsetItem> initPredicate(BdfServer bdfServer, PermissionSummary permissionSummary, SqlExportDef sqlExportDef) {
        FichothequeQueries fichothequeQueries = BdfServerUtils.resolveSelectionOptions(bdfServer, sqlExportDef.getSelectionOptions());
        return BdfServerUtils.toPredicate(bdfServer, permissionSummary, bdfServer.getDefaultWorkingLang(), fichothequeQueries);
    }

}
