/* FichothequeLib_Xml - Copyright (c) 2006-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.storage;

import java.io.IOException;
import java.util.List;
import net.fichotheque.corpus.metadata.CorpusField;
import net.fichotheque.corpus.metadata.CorpusMetadata;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.corpus.metadata.FieldOptionConstants;
import net.fichotheque.utils.CorpusMetadataUtils;
import net.fichotheque.utils.FichothequeXMLUtils;
import net.mapeadores.util.text.LabelUtils;
import net.mapeadores.util.text.MultiStringable;
import net.mapeadores.util.xml.XMLPart;
import net.mapeadores.util.xml.XMLWriter;


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

    public CorpusMetadataXMLPart(XMLWriter xmlWriter) {
        super(xmlWriter);
    }

    public void appendCorpusMetadata(CorpusMetadata corpusMetadata) throws IOException {
        openTag("corpus-metadata");
        FichothequeXMLUtils.write(corpusMetadata, this);
        appendFields(corpusMetadata);
        appendFieldGeneration(corpusMetadata);
        appendOptions(corpusMetadata);
        appendL10n(corpusMetadata);
        closeTag("corpus-metadata");
    }

    private void appendFields(CorpusMetadata corpusMetadata) throws IOException {
        openTag("fields");
        if (corpusMetadata.isWithSubtitle()) {
            addEmptyElement(FieldKey.SPECIAL_SUBTITLE);
        }
        for (CorpusField corpusField : corpusMetadata.getPropList()) {
            startOpenTag(FieldKey.PROP_CATEGORY_STRING);
            addAttribute("name", corpusField.getFieldName());
            appendFicheItemAttribute(corpusField);
            closeEmptyTag();

        }
        for (CorpusField corpusField : corpusMetadata.getInfoList()) {
            startOpenTag(FieldKey.INFO_CATEGORY_STRING);
            addAttribute("name", corpusField.getFieldName());
            appendFicheItemAttribute(corpusField);
            closeEmptyTag();
        }
        for (CorpusField corpusField : corpusMetadata.getSectionList()) {
            startOpenTag(FieldKey.SECTION_CATEGORY_STRING);
            addAttribute("name", corpusField.getFieldName());
            closeEmptyTag();
        }
        closeTag("fields");
    }

    private void appendFicheItemAttribute(CorpusField corpusField) throws IOException {
        addAttribute("fiche-item", corpusField.getFicheItemType());
    }

    private void appendL10n(CorpusMetadata corpusMetadata) throws IOException {
        openTag("l10n");
        List<CorpusField> list = CorpusMetadataUtils.getCorpusFieldList(corpusMetadata);
        for (CorpusField corpusField : list) {
            startOpenTag("field");
            addAttribute("field-key", corpusField.getFieldString());
            endOpenTag();
            LabelUtils.addLabels(this, corpusField.getLabels());
            closeTag("field");
        }
        closeTag("l10n");
    }

    private void appendFieldGeneration(CorpusMetadata corpusMetadata) throws IOException {
        String rawString = corpusMetadata.getFieldGeneration().getRawString();
        if (!rawString.isEmpty()) {
            openTag("field-generation");
            addCData(rawString);
            closeTag("field-generation", false);
        }
    }

    private void appendOptions(CorpusMetadata corpusMetadata) throws IOException {
        openTag("options");
        CorpusField geolocalisationField = corpusMetadata.getGeolocalisationField();
        if (geolocalisationField != null) {
            String value = null;
            appendOption(FieldOptionConstants.GEOLOCALISATIONFIELD_OPTION, value, geolocalisationField);
        }
        appendOptions(corpusMetadata.getCorpusField(FieldKey.ID));
        appendOptions(corpusMetadata.getCorpusField(FieldKey.TITLE));
        appendOptions(corpusMetadata.getCorpusField(FieldKey.LANG));
        appendOptions(corpusMetadata.getCorpusField(FieldKey.OWNERS));
        CorpusField subtitleField = corpusMetadata.getCorpusField(FieldKey.SUBTITLE);
        if (subtitleField != null) {
            appendOptions(subtitleField);
        }
        for (CorpusField corpusField : corpusMetadata.getPropList()) {
            appendOptions(corpusField);
        }
        for (CorpusField corpusField : corpusMetadata.getInfoList()) {
            appendOptions(corpusField);
        }
        for (CorpusField corpusField : corpusMetadata.getSectionList()) {
            appendOptions(corpusField);
        }
        closeTag("options");
    }

    private void appendOptions(CorpusField corpusField) throws IOException {
        for (String optionName : corpusField.getOptionNameSet()) {
            Object value = corpusField.getOption(optionName);
            if (value instanceof String) {
                appendOption(optionName, (String) value, corpusField);
            } else if (value instanceof MultiStringable) {
                appendOption(optionName, ((MultiStringable) value).toStringArray(), corpusField);
            }

        }
    }

    private void appendOption(String name, String value, CorpusField corpusField) throws IOException {
        startOpenTag("option");
        addAttribute("name", name);
        addAttribute("field-key", corpusField.getFieldString());
        addAttribute("value", value);
        closeEmptyTag();
    }

    private void appendOption(String name, String[] values, CorpusField corpusField) throws IOException {
        startOpenTag("option");
        addAttribute("name", name);
        addAttribute("field-key", corpusField.getFieldString());
        endOpenTag();
        for (String value : values) {
            if ((value != null) && (value.length() > 0)) {
                addSimpleElement("value", value);
            } else {
                addEmptyElement("value");
            }
        }
        closeTag("option");
    }

}
