/* FichothequeLib_Tools - 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 net.fichotheque.tools.exportation.table;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import net.fichotheque.Subset;
import net.fichotheque.exportation.table.Col;
import net.fichotheque.exportation.table.ColDef;
import net.fichotheque.exportation.table.FormatColDef;
import net.fichotheque.exportation.table.SubsetTable;
import net.fichotheque.exportation.table.TableDef;
import net.fichotheque.exportation.table.TableDefItem;
import net.fichotheque.exportation.table.TableExportContext;
import net.fichotheque.exportation.table.TableInclusionDef;
import net.fichotheque.exportation.table.TableInclusionResolver;
import net.fichotheque.exportation.table.TableParameterDef;
import net.fichotheque.format.FormatContext;
import net.fichotheque.format.formatters.SourceFormatter;
import net.fichotheque.tools.format.FichothequeFormatDefEngine;
import net.fichotheque.utils.TableDefUtils;
import net.fichotheque.utils.TableExportUtils;
import net.mapeadores.util.logging.LogUtils;


/**
 *
 * @author Vincent Calame
 */
public class SubsetTableBuilder {

    private final Subset subset;
    private final List<ColDef> colDefList = new ArrayList<ColDef>();
    private final List<Col> colList = new ArrayList<Col>();
    private final Map<String, String> parameterMap = new HashMap<String, String>();

    public SubsetTableBuilder(Subset subset) {
        this.subset = subset;
    }

    public SubsetTableBuilder addCol(ColDef colDef, SourceFormatter formatter) {
        colDefList.add(colDef);
        colList.add(TableExportUtils.toCol(colDef, formatter));
        return this;
    }

    public SubsetTableBuilder addCol(Col col) {
        colDefList.add(col.getColDef());
        colList.add(col);
        return this;
    }

    public SubsetTableBuilder addCols(TableInclusionDef tableInclusionDef, TableExportContext tableExportContext) {
        TableInclusionResolver tableInclusionResolver = tableExportContext.getTableInclusionResolverProvider().getTableInclusionResolver(tableInclusionDef.getNameSpace());
        if (tableInclusionResolver != null) {
            Col[] resolvedColArray = tableInclusionResolver.resolve(tableInclusionDef, subset, tableExportContext);
            for (Col col : resolvedColArray) {
                SubsetTableBuilder.this.addCol(col);
            }
        }
        return this;
    }

    public SubsetTableBuilder addCol(FormatColDef colDef, FormatContext formatContext, boolean ignoreMissingCorpusField, String defaultSeparator) {
        SourceFormatter formatter = FichothequeFormatDefEngine.compute(subset, ((FormatColDef) colDef).getFichothequeFormatDef(), LogUtils.NULL_MESSAGEHANDLER, FichothequeFormatDefEngine.parameters(formatContext).defaultGlobalSelect(true).ignoreMissingCorpusField(ignoreMissingCorpusField).defaultSeparator(defaultSeparator));
        if (formatter != null) {
            SubsetTableBuilder.this.addCol(colDef, formatter);
        }
        return this;
    }

    public SubsetTableBuilder addParameter(String parameterName, String parameterValue) {
        parameterMap.put(parameterName, parameterValue);
        return this;
    }

    public SubsetTableBuilder populate(TableDef tableDef, TableExportContext tableExportContext) {
        return populate(tableDef, tableExportContext, false, ";");
    }

    public SubsetTableBuilder populate(TableDef tableDef, TableExportContext tableExportContext, boolean ignoreMissingCorpusField, String defaultSeparator) {
        List<TableDefItem> defItemList = tableDef.getDefItemList();
        for (TableDefItem defItem : defItemList) {
            if (defItem instanceof TableParameterDef) {
                TableParameterDef tableParameterDef = (TableParameterDef) defItem;
                addParameter(tableParameterDef.getParameterName(), tableParameterDef.getParameterValue());
            }
        }
        for (TableDefItem defItem : defItemList) {
            if (defItem instanceof FormatColDef) {
                addCol((FormatColDef) defItem, tableExportContext.getFormatContext(), ignoreMissingCorpusField, defaultSeparator);
            } else if (defItem instanceof TableInclusionDef) {
                addCols((TableInclusionDef) defItem, tableExportContext);
            }
        }
        return this;
    }

    public SubsetTable toSubsetTable() {
        List<ColDef> finalColDefList = TableDefUtils.wrap(colDefList.toArray(new ColDef[colDefList.size()]));
        List<Col> finalColList = TableExportUtils.wrap(colList.toArray(new Col[colList.size()]));
        return new InternalSubsetTable(subset, finalColDefList, finalColList, parameterMap);
    }

    public static SubsetTableBuilder init(Subset subset) {
        return new SubsetTableBuilder(subset);
    }


    private static class InternalSubsetTable implements SubsetTable {

        private final Subset subset;
        private final List<ColDef> colDefList;
        private final List<Col> colList;
        private final Map<String, String> parameterMap;

        private InternalSubsetTable(Subset subset, List<ColDef> colDefList, List<Col> colList, Map<String, String> parameterMap) {
            this.subset = subset;
            this.colDefList = colDefList;
            this.colList = colList;
            this.parameterMap = parameterMap;
        }

        @Override
        public Subset getSubset() {
            return subset;
        }

        @Override
        public List<ColDef> getColDefList() {
            return colDefList;
        }

        @Override
        public List<Col> getColList() {
            return colList;
        }

        @Override
        public String getParameterValue(String parameterName) {
            return parameterMap.get(parameterName);
        }

    }

}
