/* FichothequeLib_Tools - Copyright (c) 2013-2024 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.importation.dom;

import java.text.ParseException;
import java.util.function.Consumer;
import net.fichotheque.Fichotheque;
import net.fichotheque.Subset;
import net.fichotheque.SubsetKey;
import net.fichotheque.corpus.Corpus;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.include.IncludeKey;
import net.fichotheque.tools.importation.LabelImportBuilder;
import net.mapeadores.util.text.CleanedString;
import net.mapeadores.util.xml.DOMUtils;
import org.w3c.dom.Element;


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

    private final Fichotheque fichotheque;
    private final LabelImportBuilder labelImportBuilder;

    public LabelImportDOMReader(Fichotheque fichotheque, LabelImportBuilder labelImportBuilder) {
        this.fichotheque = fichotheque;
        this.labelImportBuilder = labelImportBuilder;
    }

    public LabelImportDOMReader read(Element element) {
        DOMUtils.readChildren(element, new RootConsumer());
        return this;
    }

    public static LabelImportDOMReader init(Fichotheque fichotheque, LabelImportBuilder labelImportBuilder) {
        return new LabelImportDOMReader(fichotheque, labelImportBuilder);
    }


    private class RootConsumer implements Consumer<Element> {

        private final MetadataConsumer metadataConsumer;
        private final CorpusConsumer corpusConsumer;

        private RootConsumer() {
            metadataConsumer = new MetadataConsumer();
            corpusConsumer = new CorpusConsumer();
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            switch (tagName) {
                case "fichotheque": {
                    metadataConsumer.setSubset(null);
                    DOMUtils.readChildren(element, metadataConsumer);
                    break;
                }
                case "corpus": {
                    Subset subset = getSubset(element, SubsetKey.CATEGORY_CORPUS);
                    if (subset != null) {
                        metadataConsumer.setSubset(subset);
                        DOMUtils.readChildren(element, metadataConsumer);
                        corpusConsumer.setCorpus((Corpus) subset);
                        DOMUtils.readChildren(element, corpusConsumer);

                    }
                    break;
                }
                case "thesaurus": {
                    Subset subset = getSubset(element, SubsetKey.CATEGORY_THESAURUS);
                    if (subset != null) {
                        metadataConsumer.setSubset(subset);
                        DOMUtils.readChildren(element, metadataConsumer);
                    }
                    break;
                }
                case "sphere": {
                    Subset subset = getSubset(element, SubsetKey.CATEGORY_SPHERE);
                    if (subset != null) {
                        metadataConsumer.setSubset(subset);
                        DOMUtils.readChildren(element, metadataConsumer);
                    }
                    break;
                }
                case "album": {
                    Subset subset = getSubset(element, SubsetKey.CATEGORY_ALBUM);
                    if (subset != null) {
                        metadataConsumer.setSubset(subset);
                        DOMUtils.readChildren(element, metadataConsumer);
                    }
                    break;
                }
                case "addenda": {
                    Subset subset = getSubset(element, SubsetKey.CATEGORY_ADDENDA);
                    if (subset != null) {
                        metadataConsumer.setSubset(subset);
                        DOMUtils.readChildren(element, metadataConsumer);
                    }
                    break;
                }
            }

        }

        private Subset getSubset(Element element, short category) {
            String name = element.getAttribute("name");
            try {
                SubsetKey subsetKey = SubsetKey.parse(category, name);
                return fichotheque.getSubset(subsetKey);
            } catch (ParseException pe) {
                return null;
            }
        }

    }


    private class MetadataConsumer implements Consumer<Element> {

        private Subset subset;

        private MetadataConsumer() {
        }

        private void setSubset(Subset subset) {
            this.subset = subset;
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            if (tagName.equals("phrase")) {
                String name = element.getAttribute("name");
                if (name.length() > 0) {
                    String valueString = DOMUtils.readSimpleElement(element);
                    CleanedString value = CleanedString.newInstance(valueString);
                    if (subset == null) {
                        labelImportBuilder.addFichothequePhrase(name, value);
                    } else {
                        labelImportBuilder.addSubsetPhrase(subset, name, value);
                    }
                }
            } else if (tagName.equals("title")) {
                String valueString = DOMUtils.readSimpleElement(element);
                CleanedString value = CleanedString.newInstance(valueString);
                if (subset == null) {
                    labelImportBuilder.addFichothequePhrase(null, value);
                } else {
                    labelImportBuilder.addSubsetPhrase(subset, null, value);
                }
            }
        }

    }


    private class CorpusConsumer implements Consumer<Element> {

        private Corpus corpus;

        private CorpusConsumer() {
        }

        private void setCorpus(Corpus corpus) {
            this.corpus = corpus;
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            String valueString = DOMUtils.readSimpleElement(element);
            CleanedString value = CleanedString.newInstance(valueString);
            if (tagName.equals("field")) {
                try {
                    FieldKey fieldKey = FieldKey.parse(element.getAttribute("field-key"));
                    labelImportBuilder.addFieldKeyImport(corpus, fieldKey, value);
                } catch (ParseException pe) {
                }
            } else if (tagName.equals("include")) {
                try {
                    IncludeKey includeKey = IncludeKey.parse(element.getAttribute("include-key"));
                    labelImportBuilder.addIncludeKeyImport(corpus, includeKey, value);
                } catch (ParseException pe) {
                }
            }
        }

    }

}
