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

import java.io.IOException;
import net.fichotheque.Fichotheque;
import net.fichotheque.Metadata;
import net.fichotheque.Subset;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.corpus.metadata.CorpusMetadata;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.thesaurus.Motcle;
import net.fichotheque.thesaurus.Thesaurus;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.text.Label;
import net.mapeadores.util.text.Labels;
import net.mapeadores.util.text.Phrase;
import net.mapeadores.util.xml.AppendableXMLWriter;
import net.mapeadores.util.xml.XMLPart;
import net.mapeadores.util.xml.XMLUtils;
import net.mapeadores.util.xml.XMLWriter;


/**
 *
 * @author Vincent Calame
 */
public class LibsXMLPart extends XMLPart {

    public final static String SPECIAL_INTITULES = "intitules";
    private final Lang lang;

    public LibsXMLPart(XMLWriter xmlWriter, Lang lang) {
        super(xmlWriter);
        this.lang = lang;
    }

    public void appendIntituleLibs(Fichotheque fichotheque) throws IOException {
        startOpenTag("libs");
        endOpenTag();
        for (Corpus corpus : fichotheque.getCorpusList()) {
            appendCorpusIntituleLibs(corpus, true);
        }
        for (Thesaurus thesaurus : fichotheque.getThesaurusList()) {
            appendThesaurusIntituleLibs(thesaurus, true);
        }
        closeTag("libs");
    }

    public void appendSubsetLibs(Subset subset) throws IOException {
        if (subset instanceof Thesaurus) {
            appendThesaurusLibs((Thesaurus) subset);
        } else if (subset instanceof Corpus) {
            appendCorpusLibs(((Corpus) subset).getCorpusMetadata());
        }
    }

    public void appendThesaurusLibs(Thesaurus thesaurus) throws IOException {
        startOpenTag("libs");
        addAttribute("category", "thesaurus");
        addAttribute("thesaurus", thesaurus.getSubsetName());
        endOpenTag();
        appendThesaurusIntituleLibs(thesaurus, false);
        for (Motcle motcle : thesaurus.getFirstLevelList()) {
            appendMotcleLib(motcle, true);
        }
        closeTag("libs");
    }

    private void appendThesaurusIntituleLibs(Thesaurus thesaurus, boolean withThesaurusName) throws IOException {
        String thesaurusName = (withThesaurusName) ? thesaurus.getSubsetName() : null;
        appendPhraseLibs(thesaurus.getThesaurusMetadata(), "thesaurus", thesaurusName);
    }

    public void appendCorpusLibs(CorpusMetadata corpusMetadata) throws IOException {
        startOpenTag("libs");
        addAttribute("category", "metadata");
        addAttribute("corpus", corpusMetadata.getCorpus().getSubsetName());
        endOpenTag();
        appendCorpusIntituleLibs(corpusMetadata.getCorpus(), false);
        appendCorpusFieldLib(corpusMetadata.getCorpusField(FieldKey.ID));
        appendCorpusFieldLib(corpusMetadata.getCorpusField(FieldKey.LANG));
        appendCorpusFieldLib(corpusMetadata.getCorpusField(FieldKey.OWNERS));
        appendCorpusFieldLib(corpusMetadata.getCorpusField(FieldKey.TITLE));
        appendCorpusFieldLib(corpusMetadata.getCorpusField(FieldKey.SUBTITLE));
        for (CorpusField corpusField : corpusMetadata.getPropList()) {
            appendCorpusFieldLib(corpusField);
        }
        for (CorpusField corpusField : corpusMetadata.getInfoList()) {
            appendCorpusFieldLib(corpusField);
        }
        for (CorpusField corpusField : corpusMetadata.getSectionList()) {
            appendCorpusFieldLib(corpusField);
        }
        closeTag("libs");
    }

    private void appendCorpusIntituleLibs(Corpus corpus, boolean withCorpusName) throws IOException {
        String corpusName = (withCorpusName) ? corpus.getSubsetName() : null;
        appendPhraseLibs(corpus.getCorpusMetadata(), "corpus", corpusName);
    }

    private void appendPhraseLibs(Metadata metadata, String categoryString, String subsetId) throws IOException {
        for (Phrase phrase : metadata.getPhrases()) {
            appendPhraseLib(phrase, categoryString, subsetId);
        }
    }

    private void appendPhraseLib(Phrase intitule, String subsetCategory, String corpusName) throws IOException {
        startLib();
        addAttribute(subsetCategory, corpusName);
        addAttribute("intitule-name", intitule.getName());
        endLib(intitule);
    }

    private void appendCorpusFieldLib(CorpusField corpusField) throws IOException {
        if (corpusField == null) {
            return;
        }
        FieldKey fieldKey = corpusField.getFieldKey();
        String fieldKeyString = fieldKey.getKeyString();
        if (fieldKey.isProp()) {
            fieldKeyString = "propriete_" + fieldKey.getFieldName();
        } else if (fieldKey.isInfo()) {
            fieldKeyString = "information_" + fieldKey.getFieldName();
        } else if (fieldKey.isSpecial()) {
            switch (fieldKey.getKeyString()) {
                case FieldKey.SPECIAL_TITLE:
                    fieldKeyString = "titre";
                    break;
                case FieldKey.SPECIAL_SUBTITLE:
                    fieldKeyString = "soustitre";
                    break;
                case FieldKey.SPECIAL_OWNERS:
                    fieldKeyString = "redacteurs";
                    break;
            }
        }
        startLib();
        addAttribute("field-key", fieldKeyString);
        endLib(corpusField.getLabels());
    }

    private void appendMotcleLib(Motcle motcle, boolean recursive) throws IOException {
        startLib();
        addAttribute("id", String.valueOf(motcle.getId()));
        addAttribute("idths", String.valueOf(motcle.getId()));
        addAttribute("thesaurus", motcle.getSubsetName());
        String idalpha = motcle.getIdalpha();
        if (idalpha != null) {
            addAttribute("idalpha", idalpha);
        }
        endLib(motcle.getLabels());
        if (recursive) {
            for (Motcle child : motcle.getChildList()) {
                appendMotcleLib(child, recursive);
            }
        }
    }

    private void startLib() throws IOException {
        startOpenTag("lib");
    }

    private void endLib(Labels labels) throws IOException {
        endOpenTag();
        Label label = labels.getLangPartCheckedLabel(lang);
        if (label != null) {
            addText(label.getLabelString());
        }
        closeTag("lib", false);
    }

    private void unknown(String key) throws IOException {
        startOpenTag("libs");
        addAttribute("unknown", key);
        closeEmptyTag();
    }

    public static String getLibsXML(Lang lang, Fichotheque fichotheque, SubsetKey subsetKey, boolean withTabs) {
        StringBuilder buf = new StringBuilder(256);
        AppendableXMLWriter xmlWriter = XMLUtils.toXMLWriter(buf, (withTabs) ? 0 : -999);
        try {
            xmlWriter.appendXMLDeclaration();
            LibsXMLPart libsXMLPart = new LibsXMLPart(xmlWriter, lang);
            Subset subset = fichotheque.getSubset(subsetKey);
            if (subset == null) {
                libsXMLPart.unknown(subsetKey.getKeyString());
            } else {
                libsXMLPart.appendSubsetLibs(subset);
            }
        } catch (IOException ioe) {
        }
        return buf.toString();
    }

    public static String getLibsXML(Lang lang, Fichotheque fichotheque, String special, boolean withTabs) {
        StringBuilder buf = new StringBuilder(256);
        AppendableXMLWriter xmlWriter = XMLUtils.toXMLWriter(buf, (withTabs) ? 0 : -999);
        try {
            xmlWriter.appendXMLDeclaration();
            LibsXMLPart libsXMLPart = new LibsXMLPart(xmlWriter, lang);
            if (special.equals(SPECIAL_INTITULES)) {
                libsXMLPart.appendIntituleLibs(fichotheque);
            } else {
                libsXMLPart.unknown(special);
            }
        } catch (IOException ioe) {
        }
        return buf.toString();
    }

}
