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

import java.text.ParseException;
import java.util.function.Consumer;
import net.fichotheque.Fichotheque;
import net.fichotheque.corpus.fiche.Cdatadiv;
import net.fichotheque.corpus.fiche.FicheBlocks;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.importation.ImportationContext;
import net.fichotheque.tools.corpus.FicheChangeBuilder;
import net.fichotheque.tools.dom.FicheDOMReader;
import net.fichotheque.tools.importation.corpus.EditFicheImportBuilder;
import net.fichotheque.utils.FicheUtils;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.primitives.FuzzyDate;
import net.mapeadores.util.xml.DOMUtils;
import net.mapeadores.util.xml.XMLUtils;
import org.w3c.dom.Element;


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

    private final EditFicheImportBuilder ficheImportBuilder;
    private final Fichotheque fichotheque;
    private final ImportationContext importationContext;

    public FicheImportDOMReader(EditFicheImportBuilder ficheImportBuilder, Fichotheque fichotheque, ImportationContext importationContext) {
        this.ficheImportBuilder = ficheImportBuilder;
        this.fichotheque = fichotheque;
        this.importationContext = importationContext;
    }

    public FicheImportDOMReader read(Element element) {
        RootConsumer rootConsumer = new RootConsumer();
        DOMUtils.readChildren(element, rootConsumer);
        rootConsumer.readOthers(element);
        return this;
    }

    public static FicheImportDOMReader init(EditFicheImportBuilder ficheImportBuilder, Fichotheque fichotheque, ImportationContext importationContext) {
        return new FicheImportDOMReader(ficheImportBuilder, fichotheque, importationContext);
    }


    private class RootConsumer implements Consumer<Element> {

        private final FicheDOMReader ficheDOMReader;
        private boolean withOthers = false;

        private RootConsumer() {
            ficheDOMReader = new FicheDOMReader(importationContext.getHtmlCleaner());
            ficheDOMReader.setAppend(true);
        }

        public void readOthers(Element element) {
            if (!withOthers) {
                return;
            }
            ficheImportBuilder.getFicheChangeBuilder().appendFiche(ficheDOMReader.readFlatFiche(element));
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            switch (tagName) {
                case "fiche":
                    ficheImportBuilder.getFicheChangeBuilder().appendFiche(ficheDOMReader.readFiche(element));
                    break;
                case "attr":
                    ImportationDomUtils.readAttrElement(element, ficheImportBuilder.getAttributeChangeBuilder());
                    break;
                case "chrono":
                    String creationString = element.getAttribute("creation");
                    if (creationString.length() > 0) {
                        try {
                            ficheImportBuilder.setCreationDate(FuzzyDate.parse(creationString));
                        } catch (ParseException die) {

                        }
                    }
                    break;
                case "removed":
                    DOMUtils.readChildren(element, new RemovedConsumer(ficheImportBuilder.getFicheChangeBuilder()));
                    break;
                case "liens":
                    String type = element.getAttribute("type");
                    LiensImportDOMReader.init(fichotheque, ficheImportBuilder.getLiensImportBuilder(), type)
                            .read(element);
                    break;
                case "lang": {
                    String langString = XMLUtils.getData(element);
                    if (langString.isEmpty()) {
                        ficheImportBuilder.getFicheChangeBuilder().setLang(null);
                    } else {
                        try {
                            Lang lang = Lang.parse(langString);
                            ficheImportBuilder.getFicheChangeBuilder().setLang(lang);
                        } catch (ParseException pe) {

                        }
                    }
                    break;
                }
                case "html":
                    readHtml(element);
                    break;
                default:
                    withOthers = true;
            }
        }

        private void readHtml(Element element) {
            FicheChangeBuilder ficheChangeBuilder = ficheImportBuilder.getFicheChangeBuilder();
            String cdata = XMLUtils.getRawData(element);
            try {
                FieldKey convertFieldKey = FieldKey.parse(element.getAttribute("convert"));
                FicheBlocks ficheBlocks = importationContext.getHtmlConverter().convertHtml(cdata);
                if (convertFieldKey.isSection()) {
                    ficheChangeBuilder.putSection(convertFieldKey, ficheBlocks);
                }
            } catch (ParseException pe) {

            }
            try {
                FieldKey archiveFieldKey = FieldKey.parse(element.getAttribute("archive"));
                if (archiveFieldKey.isSection()) {
                    Cdatadiv cdatadiv = new Cdatadiv();
                    cdatadiv.setCdata(importationContext.getHtmlCleaner().cleanHtml(cdata));
                    ficheChangeBuilder.putSection(archiveFieldKey, FicheUtils.toFicheBlocks(cdatadiv));
                }
            } catch (ParseException pe) {

            }
        }

    }


    private static class RemovedConsumer implements Consumer<Element> {

        private final FicheChangeBuilder ficheChangeBuilder;

        private RemovedConsumer(FicheChangeBuilder ficheChangeBuilder) {
            this.ficheChangeBuilder = ficheChangeBuilder;
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            switch (tagName) {
                case "key": {
                    try {
                        FieldKey fieldKey = FieldKey.parse(XMLUtils.getData(element));
                        ficheChangeBuilder.removeField(fieldKey);
                    } catch (ParseException pe) {

                    }
                    break;
                }
            }
        }

    }

}
