/* FichothequeLib_Tools - Copyright (c) 2016-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.inclusionresolvers;

import java.text.ParseException;
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.TableDef;
import net.fichotheque.exportation.table.TableExportContext;
import net.fichotheque.exportation.table.TableInclusionDef;
import net.fichotheque.exportation.table.TableInclusionResolver;
import net.fichotheque.format.FormatSource;
import net.fichotheque.format.formatters.SourceFormatter;
import net.fichotheque.tools.exportation.table.TableDefParser;
import net.fichotheque.tools.format.FichothequeFormatDefEngine;
import net.fichotheque.utils.TableDefUtils;
import net.fichotheque.utils.TableExportUtils;
import net.mapeadores.util.format.FormatConstants;
import net.mapeadores.util.instruction.Argument;
import net.mapeadores.util.instruction.Instruction;
import net.mapeadores.util.instruction.InstructionParser;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.LangContext;
import net.mapeadores.util.localisation.ListLangContext;
import net.mapeadores.util.localisation.UserLangContext;
import net.mapeadores.util.logging.LineMessageHandler;
import net.mapeadores.util.logging.LogUtils;
import net.mapeadores.util.text.Labels;


/**
 *
 * @author Vincent Calame
 */
public class MultilangInclusionResolver implements TableInclusionResolver {

    public final static String NAMESPACE = "multilang";

    public MultilangInclusionResolver() {

    }

    @Override
    public boolean test(TableInclusionDef tableInclusionDef, Subset subset, TableExportContext tableExportContext, int lineNumber, LineMessageHandler lineMessageHandler) {
        String nameSpace = tableInclusionDef.getNameSpace();
        if (!nameSpace.equals(NAMESPACE)) {
            return false;
        }
        Col[] colArray = build(tableInclusionDef, subset, tableExportContext, lineNumber, lineMessageHandler);
        return (colArray.length > 0);
    }

    @Override
    public Col[] resolve(TableInclusionDef tableInclusionDef, Subset subset, TableExportContext tableExportContext) {
        String nameSpace = tableInclusionDef.getNameSpace();
        if (!nameSpace.equals(NAMESPACE)) {
            return TableExportUtils.EMPTY_COLARRAY;
        }
        return build(tableInclusionDef, subset, tableExportContext, 1, LogUtils.NULL_LINEMESSAGEHANDLER);
    }

    private Col[] build(TableInclusionDef tableInclusionDef, Subset subset, TableExportContext tableExportContext, int lineNumber, LineMessageHandler lineMessageHandler) {
        List<String> configLineList = tableInclusionDef.getConfigLineList();
        int lineLength = configLineList.size();
        if (lineLength < 2) {
            return TableExportUtils.EMPTY_COLARRAY;
        }
        String colnameLine = configLineList.get(0);
        if (colnameLine.startsWith("%") || colnameLine.startsWith("!")) {
            return TableExportUtils.EMPTY_COLARRAY;
        }
        String patternLine = null;
        String instructionLine = null;
        if (lineLength > 2) {
            patternLine = configLineList.get(2);
            if (lineLength > 3) {
                instructionLine = configLineList.get(3);
            }
        }
        Instruction instruction = InstructionParser.parse(configLineList.get(1), LogUtils.encapsulate(lineMessageHandler, FormatConstants.SEVERE_SYNTAX, lineNumber + 2));
        Map<Lang, SourceFormatter> langMap = new HashMap<Lang, SourceFormatter>();
        FormatColDef firstColDef = null;
        for (Argument argument : instruction) {
            String value = argument.getValue();
            if (value.length() > 0) {
                try {
                    Lang lang = Lang.parse(argument.getKey());
                    StringBuilder buf = new StringBuilder();
                    buf.append(colnameLine);
                    buf.append('\n');
                    buf.append(value);
                    buf.append('\n');
                    if (patternLine != null) {
                        buf.append(patternLine);
                        buf.append('\n');
                        if (instructionLine != null) {
                            buf.append(instructionLine);
                            buf.append('\n');
                        }
                    }
                    TableDef tableDef = TableDefParser.parse(buf.toString(), subset, tableExportContext, lineMessageHandler, lineNumber);
                    if (!tableDef.getDefItemList().isEmpty()) {
                        FormatColDef formatColDef = (FormatColDef) tableDef.getDefItemList().get(0);
                        SourceFormatter sourceFormatter = FichothequeFormatDefEngine.compute(subset, formatColDef.getFichothequeFormatDef(), TableDefUtils.toFormatDefMessageHandler(lineMessageHandler, lineNumber), FichothequeFormatDefEngine.parameters(tableExportContext.getFormatContext()).defaultGlobalSelect(true).ignoreMissingCorpusField(false));
                        if (sourceFormatter != null) {
                            if (firstColDef == null) {
                                firstColDef = formatColDef;
                            }
                            langMap.put(lang, sourceFormatter);
                        }
                    }
                } catch (ParseException pe) {

                }
            }
        }
        if (firstColDef == null) {
            return TableExportUtils.EMPTY_COLARRAY;
        }
        Col[] colArray = new Col[1];
        colArray[0] = TableExportUtils.toCol(new MultilangColDef(firstColDef), new MultilangSourceFormatter(langMap));
        return colArray;
    }


    private static class MultilangColDef implements ColDef {

        private final FormatColDef firstColDef;

        private MultilangColDef(FormatColDef firstColDef) {
            this.firstColDef = firstColDef;
        }

        @Override
        public String getColName() {
            return firstColDef.getColName();
        }

        @Override
        public Labels getCustomLabels() {
            return firstColDef.getCustomLabels();
        }

        @Override
        public Object getParameterValue(String paramKey) {
            return firstColDef.getParameterValue(paramKey);
        }

    }


    private static class MultilangSourceFormatter implements SourceFormatter {

        private final Map<Lang, SourceFormatter> langMap;

        private MultilangSourceFormatter(Map<Lang, SourceFormatter> langMap) {
            this.langMap = langMap;
        }

        @Override
        public String formatSource(FormatSource formatSource) {
            LangContext langContext = formatSource.getLangContext();
            Lang lang = null;
            if (langContext instanceof ListLangContext) {
                lang = ((ListLangContext) langContext).get(0).getLang();
            } else if (langContext instanceof UserLangContext) {
                lang = ((UserLangContext) langContext).getWorkingLang();
            }
            if (lang == null) {
                return null;
            }
            SourceFormatter sourceFormatter = langMap.get(lang);
            if (sourceFormatter == null) {
                return null;
            }
            return sourceFormatter.formatSource(formatSource);
        }

    }

}
