/* FichothequeLib_Xml - Copyright (c) 2008-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.xml.extraction;

import java.io.IOException;
import java.util.List;
import java.util.Locale;
import net.fichotheque.SubsetItem;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.FicheMeta;
import net.fichotheque.corpus.fiche.FicheBlocks;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.croisement.Croisement;
import net.fichotheque.croisement.Lien;
import net.fichotheque.extraction.ExtractParameters;
import net.fichotheque.extraction.ExtractionConstants;
import net.fichotheque.extraction.def.DocumentFilter;
import net.fichotheque.extraction.def.FicheFilter;
import net.fichotheque.extraction.def.IllustrationFilter;
import net.fichotheque.extraction.def.MotcleFilter;
import net.fichotheque.extraction.def.TagNameInfo;
import net.fichotheque.extraction.filterunit.FilterUnit;
import net.fichotheque.extraction.run.FicheExtractInfo;
import net.fichotheque.extraction.run.MotcleExtractInfo;
import net.fichotheque.thesaurus.Motcle;
import net.fichotheque.utils.ExtractionUtils;
import net.fichotheque.utils.FichothequeUtils;
import net.fichotheque.utils.FilterUnits;
import net.mapeadores.util.annotation.Nullable;
import net.mapeadores.util.exceptions.NestedIOException;
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.text.LabelUtils;
import net.mapeadores.util.xml.AppendableXMLWriter;
import net.mapeadores.util.xml.XMLUtils;
import net.mapeadores.util.xml.XMLWriter;


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

    public final static FicheFilter TITLE_FICHEFILTER = new TitleFicheFilter();
    public final static IllustrationFilter DEFAULT_ILLUSTRATIONFILTER = new DefaultIllustrationFilter();
    public final static DocumentFilter DEFAULT_DOCUMENTFILTER = new DefaultDocumentFilter();
    public final static MotcleFilter LABELS_MOTCLEFILTER = new DefaultMotcleFilter(true);
    public final static MotcleFilter NONE_MOTCLEFILTER = new DefaultMotcleFilter(false);

    private ExtractionXMLUtils() {
    }

    public static int getMainWeight(Croisement croisement) {
        if (croisement == null) {
            return 0;
        }
        return croisement.getLienList().get(0).getWeight();
    }

    public static void writeCroisement(XMLWriter xmlWriter, Croisement croisement, TagNames tagNames) throws IOException {
        if (croisement == null) {
            return;
        }
        for (Lien lien : croisement.getLienList()) {
            xmlWriter.startOpenTag(tagNames.getTieTagName());
            xmlWriter.addAttribute("mode", lien.getMode());
            xmlWriter.addAttribute(tagNames.getWeightAttributeName(), lien.getWeight());
            xmlWriter.closeEmptyTag();
        }
    }

    public static void writePhrase(XMLWriter xmlWriter, SubsetItem subsetItem, String phraseName, LangContext langContext, int extractVersion) throws IOException {
        String tagName;
        if (extractVersion == ExtractionConstants.INITIAL_VERSION) {
            tagName = "intitule";
            xmlWriter.openTag("intitule");
        } else {
            tagName = "phrase";
            xmlWriter.startOpenTag(tagName);
            xmlWriter.addAttribute("name", phraseName);
            xmlWriter.endOpenTag();
        }
        if (langContext instanceof ListLangContext) {
            for (ListLangContext.Unit unit : (ListLangContext) langContext) {
                Lang lang = unit.getLang();
                Locale locale = unit.getFormatLocale();
                String title = FichothequeUtils.getNumberPhrase(subsetItem, phraseName, lang, locale);
                LabelUtils.addLabel(xmlWriter, lang, title);
            }
        } else if (langContext instanceof UserLangContext) {
            UserLangContext userLangContext = (UserLangContext) langContext;
            Lang workingLang = userLangContext.getWorkingLang();
            Locale locale = userLangContext.getFormatLocale();
            String title = FichothequeUtils.getNumberPhrase(subsetItem, phraseName, workingLang, locale);
            LabelUtils.addLabel(xmlWriter, null, title);
        }
        xmlWriter.closeTag(tagName);
    }

    public static String ficheBlocksToExtractionString(FicheBlocks ficheBlocks, ExtractParameters extractParameters, @Nullable SubsetKey defaultCorpusKey) {
        StringBuilder buf = new StringBuilder();
        AppendableXMLWriter xmlWriter = XMLUtils.toXMLWriter(buf, -999);
        try {
            xmlWriter.openTag("section");
            if (ficheBlocks != null) {
                Corpus defaultCorpus = null;
                if (defaultCorpusKey != null) {
                    defaultCorpus = (Corpus) extractParameters.getExtractionContext().getFichotheque().getSubset(defaultCorpusKey);
                }
                FicheBlockXMLPart ficheBlockXMLPart = new FicheBlockXMLPart(xmlWriter, extractParameters);
                ficheBlockXMLPart.setDefaultCorpus(defaultCorpus);
                ficheBlockXMLPart.addFicheBlocks(ficheBlocks, ExtractionUtils.SAME_CONVERTER);
            }
            xmlWriter.closeTag("section");
        } catch (IOException ioe) {
            throw new NestedIOException(ioe);
        }
        return buf.toString();
    }

    public static MotcleExtractInfo toMotcleExtractInfo(Motcle motcle, MotcleFilter motcleFilter) {
        return new SimpleMotcleExtractInfo(motcle, motcleFilter);
    }

    public static FicheExtractInfo toFicheExtractInfo(FicheMeta ficheMeta, FicheFilter ficheFilter) {
        return new SimpleFicheExtractInfo(ficheMeta, ficheFilter);
    }

    public static void addFilterParameters(XMLWriter xmlWriter, FilterUnit filterUnit) throws IOException {
        if (filterUnit == null) {
            return;
        }
        List<String> paramList = filterUnit.getParameter(ExtractionConstants.GROUPS_PARAM);
        if (!paramList.isEmpty()) {
            StringBuilder buf = new StringBuilder();
            for (String value : paramList) {
                if (buf.length() > 0) {
                    buf.append(' ');
                }
                buf.append('~');
                buf.append(value);
            }
            xmlWriter.addAttribute("groups", buf.toString());
        }
        String cellOrder = filterUnit.getFirstValue(ExtractionConstants.CELL_ORDER_PARAM);
        if (cellOrder != null) {
            xmlWriter.addAttribute("cell-order", cellOrder);
        }
        String cellFormat = filterUnit.getFirstValue(ExtractionConstants.CELL_FORMAT_PARAM);
        if (cellFormat != null) {
            xmlWriter.addAttribute("cell-format", cellFormat);
        }
    }

    public static void addCellMax(XMLWriter xmlWriter, FicheFilter ficheFilter) throws IOException {
        int cellMax = ficheFilter.getCellMax();
        if (cellMax > 0) {
            xmlWriter.addAttribute("cellmax", String.valueOf(cellMax));
        }
    }


    private static class SimpleMotcleExtractInfo implements MotcleExtractInfo {

        private final Motcle motcle;
        private final MotcleFilter motcleFilter;

        private SimpleMotcleExtractInfo(Motcle motcle, MotcleFilter motcleFilter) {
            this.motcle = motcle;
            this.motcleFilter = motcleFilter;
        }

        @Override
        public Motcle getMotcle() {
            return motcle;
        }

        @Override
        public MotcleFilter getMotcleFilter() {
            return motcleFilter;
        }

        @Override
        public Croisement getCroisement() {
            return null;
        }

    }


    private static class SimpleFicheExtractInfo implements FicheExtractInfo {

        private final FicheFilter ficheFilter;
        private final FicheMeta ficheMeta;

        private SimpleFicheExtractInfo(FicheMeta ficheMeta, FicheFilter ficheFilter) {
            this.ficheMeta = ficheMeta;
            this.ficheFilter = ficheFilter;
        }

        @Override
        public FicheFilter getFicheFilter() {
            return ficheFilter;
        }

        @Override
        public FicheMeta getFicheMeta() {
            return ficheMeta;
        }

        @Override
        public Croisement getCroisement() {
            return null;
        }

        @Override
        public Object getGroupClauseObject() {
            return null;
        }

    }


    private static class TitleFicheFilter implements FicheFilter {

        private final List<FilterUnit> filterUnitList;

        private TitleFicheFilter() {
            FilterUnit[] array = new FilterUnit[2];
            array[0] = FilterUnits.fieldKey(FieldKey.TITLE, ExtractionUtils.EMPTY_FILTERPARAMETERS);
            array[1] = FilterUnits.FICHEPHRASE_FILTERUNIT;
            filterUnitList = ExtractionUtils.wrap(array);
        }

        @Override
        public boolean isWithCorpsdefiche() {
            return false;
        }

        @Override
        public List<FilterUnit> getFilterUnitList() {
            return filterUnitList;
        }

        @Override
        public TagNameInfo getTagNameInfo() {
            return TagNameInfo.DEFAULT;
        }

    }


    private static class DefaultMotcleFilter implements MotcleFilter {

        private final boolean withLabels;

        private DefaultMotcleFilter(boolean withLabels) {
            this.withLabels = withLabels;
        }

        @Override
        public short getType() {
            return MotcleFilter.DEFAULT_TYPE;
        }


        @Override
        public TagNameInfo getTagNameInfo() {
            return TagNameInfo.DEFAULT;
        }

        @Override
        public boolean isNoneFiltering() {
            return !withLabels;
        }

        @Override
        public boolean withIcon() {
            return withLabels;
        }

        @Override
        public boolean withLevel() {
            return false;
        }

        @Override
        public boolean withLabels() {
            return withLabels;
        }

        @Override
        public boolean withFicheStylePhrase() {
            return false;
        }

        @Override
        public MotcleFilter getChildrenFilter() {
            return null;
        }

        @Override
        public MotcleFilter getParentFilter() {
            return null;
        }

        @Override
        public MotcleFilter getNextFilter() {
            return null;
        }

        @Override
        public MotcleFilter getPreviousFilter() {
            return null;
        }

        @Override
        public List<FilterUnit> getFilterUnitList() {
            return ExtractionUtils.EMPTY_FILTERUNITLIST;
        }


    }


    private static class DefaultDocumentFilter implements DocumentFilter {

        private DefaultDocumentFilter() {

        }

        @Override
        public TagNameInfo getTagNameInfo() {
            return TagNameInfo.DEFAULT;
        }

    }


    private static class DefaultIllustrationFilter implements IllustrationFilter {


        private DefaultIllustrationFilter() {

        }

        @Override
        public TagNameInfo getTagNameInfo() {
            return TagNameInfo.DEFAULT;
        }

    }


}
