/* BdfServer_Email - Copyright (c) 2015-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.email.datasource;

import fr.exemole.bdfserver.api.BdfServer;
import fr.exemole.bdfserver.api.exportation.table.TableExportParameters;
import fr.exemole.bdfserver.api.instruction.BdfParameters;
import fr.exemole.bdfserver.api.managers.TableExportManager;
import fr.exemole.bdfserver.api.users.BdfUser;
import fr.exemole.bdfserver.tools.BdfServerUtils;
import fr.exemole.bdfserver.tools.exportation.table.BdfTableExportUtils;
import fr.exemole.bdfserver.tools.exportation.table.CellConversionInit;
import fr.exemole.bdfserver.tools.users.BdfUserUtils;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Collection;
import javax.activation.DataSource;
import net.fichotheque.Subset;
import net.fichotheque.SubsetItem;
import net.fichotheque.SubsetKey;
import net.fichotheque.exportation.table.ColDefTitleProvider;
import net.fichotheque.exportation.table.SubsetTable;
import net.fichotheque.exportation.table.SumCellConverter;
import net.fichotheque.exportation.table.TableExport;
import net.fichotheque.exportation.table.TableExportConstants;
import net.fichotheque.exportation.table.TableExportContext;
import net.fichotheque.exportation.table.TableExportDef;
import net.fichotheque.extraction.ExtractionContext;
import net.fichotheque.permission.PermissionSummary;
import net.fichotheque.tools.exportation.table.CsvTableWriter;
import net.fichotheque.tools.exportation.table.TableExportEngine;
import net.fichotheque.tools.exportation.table.TableExportOds;
import net.fichotheque.tools.exportation.table.TableExportOdsFactory;
import net.fichotheque.tools.exportation.table.TableExportOdsParameters;
import net.fichotheque.utils.TableDefUtils;
import net.mapeadores.opendocument.io.odtable.OdsOptions;
import net.mapeadores.util.exceptions.NestedIOException;
import net.mapeadores.util.io.IOUtils;
import net.mapeadores.util.mimetype.MimeTypeConstants;


/**
 *
 * @author Vincent Calame
 */
public class TableExportDataSource implements DataSource {

    private final String name;
    private final String contentType;
    private final String charset;
    private final String content;
    private final byte[] contentArray;

    private TableExportDataSource(String name, String contentType, String charset, String content) {
        this.name = name;
        this.contentType = contentType;
        this.charset = charset;
        this.content = content;
        this.contentArray = null;
    }

    private TableExportDataSource(String name, String contentType, byte[] contentArray) {
        this.name = name;
        this.contentType = contentType;
        this.charset = null;
        this.content = null;
        this.contentArray = contentArray;
    }

    @Override
    public String getContentType() {
        return contentType;
    }

    @Override
    public String getName() {
        return name;
    }

    @Override
    public InputStream getInputStream() throws IOException {
        if (content != null) {
            return IOUtils.toInputStream(content, charset);
        } else {
            return new ByteArrayInputStream(contentArray);
        }
    }

    @Override
    public OutputStream getOutputStream() throws IOException {
        throw new IOException("no editable source");
    }

    public static TableExportDataSource build(BdfParameters bdfParameters, Subset subset, Collection<SubsetItem> subsetItems, TableExportParameters tableExportParameters, String extension, String charset) {
        BdfServer bdfServer = bdfParameters.getBdfServer();
        PermissionSummary permissionSummary = bdfParameters.getPermissionSummary();
        BdfUser bdfUser = bdfParameters.getBdfUser();
        if (!permissionSummary.hasAccess(subset)) {
            throw new IllegalStateException("Not access to subset");
        }
        SubsetKey subsetKey = subset.getSubsetKey();
        StringBuilder nameBuilder = new StringBuilder();
        nameBuilder.append(subsetKey);
        TableExportManager tableExportManager = bdfServer.getTableExportManager();
        SubsetTable subsetTable = null;
        String tableExportName = tableExportParameters.getTableExportName();
        TableExportDef tableExportDef = null;
        if (tableExportName != null) {
            TableExport tableExport = tableExportManager.getTableExport(tableExportName);
            if (tableExport != null) {
                tableExportDef = tableExport.getTableExportDef();
                subsetTable = tableExport.getSubsetTable(subsetKey);
                if (subsetTable != null) {
                    nameBuilder.append("-");
                    nameBuilder.append(tableExportName);
                }
            }
        }
        if (subsetTable == null) {
            subsetTable = BdfTableExportUtils.toDefaultSubsetTable(bdfServer, subset, tableExportParameters.getDefaulFicheTableParameters(), permissionSummary);
        }
        nameBuilder.append(".");
        nameBuilder.append(extension);
        String contentType;
        TableExportContext tableExportContext = bdfServer.getTableExportContext();
        ExtractionContext extractionContext = bdfParameters.getDefaultExtractionContext();
        SumCellConverter cellConverter = CellConversionInit.subsetTable(bdfServer, extractionContext, subsetTable, tableExportDef).getCellConverter();
        if (extension.equals("csv")) {
            contentType = MimeTypeConstants.CSV + ";charset=" + charset;
            StringBuilder buf = new StringBuilder();
            CsvTableWriter csvTableWriter = new CsvTableWriter(subsetTable.getColDefList(), buf, bdfParameters.getUserLangContext());
            ColDefTitleProvider colDefTitleProvider = getColDefTitleProvider(tableExportParameters, tableExportContext, bdfUser, subset);
            if (colDefTitleProvider != null) {
                csvTableWriter.appendColumnHeader(colDefTitleProvider);
            }
            TableExportEngine.exportSubset(subsetTable, csvTableWriter, cellConverter, subsetItems);
            return new TableExportDataSource(nameBuilder.toString(), contentType, charset, buf.toString());
        } else if (extension.equals("ods")) {
            contentType = MimeTypeConstants.ODS;
            OdsOptions odsOptions = BdfServerUtils.buildOdsOptions(bdfServer, "bdf://this/css/ods/tableexport.css")
                    .supplementarySheetWriter(BdfUserUtils.getSupplementarySheetWriter(bdfParameters));
            TableExportOdsParameters tableExportOdsParameters = TableExportOdsParameters.init(tableExportContext, bdfParameters.getUserLangContext())
                    .setSumCellConverter(cellConverter)
                    .setHeaderType(tableExportParameters.getHeaderType());
            TableExportOds tableExportOds = TableExportOdsFactory.unique(subsetTable, subsetItems, tableExportOdsParameters, odsOptions);
            ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
            try {
                tableExportOds.write(outputStream, true);
            } catch (IOException ioe) {
                throw new NestedIOException(ioe);
            }
            return new TableExportDataSource(nameBuilder.toString(), contentType, outputStream.toByteArray());
        } else {
            throw new IllegalArgumentException("Unable to handle this extension: " + extension);
        }
    }

    private static ColDefTitleProvider getColDefTitleProvider(TableExportParameters tableExportParameters, TableExportContext tableExportContext, BdfUser bdfUser, Subset subset) {
        switch (tableExportParameters.getHeaderType()) {
            case TableExportConstants.COLUMNTITLE_HEADER:
                return TableDefUtils.getLabelColDefTitleProvider(bdfUser.getWorkingLang(), tableExportContext.getSourceLabelProvider(), subset);
            case TableExportConstants.COLUMNKEY_HEADER:
                return TableDefUtils.KEY_COLDEFTITLEPROVIDER;
            default:
                return null;
        }
    }

}
