/* 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.ArrayList;
import java.util.List;
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.fiche.ParaItem;
import net.fichotheque.corpus.metadata.FieldKey;
import net.fichotheque.importation.ImportationContext;
import net.fichotheque.tools.conversion.ConversionUtils;
import net.fichotheque.tools.corpus.FicheChangeBuilder;
import net.fichotheque.tools.dom.FicheChangeDOMReader;
import net.fichotheque.tools.importation.corpus.EditFicheImportBuilder;
import net.fichotheque.utils.FicheUtils;
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);
        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 FicheChangeDOMReader ficheChangeDOMReader;

        private RootConsumer() {
            ficheChangeDOMReader = new FicheChangeDOMReader(ficheImportBuilder.getFicheChangeBuilder(), importationContext);
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            switch (tagName) {
                case "fiche":
                    ficheChangeDOMReader.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 "ties":
                case "liens":
                    String type = element.getAttribute("type");
                    TiesImportDOMReader.init(fichotheque, ficheImportBuilder.getTiesImportBuilder(), type)
                            .read(element);
                    break;
                case "html":
                    readHtml(element);
                    break;
                default:
                    ficheChangeDOMReader.readFicheChild(element);
                    break;
            }
        }

        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.appendSection(convertFieldKey, ficheBlocks);
                } else {
                    List<ParaItem> paraItems = new ArrayList<ParaItem>();
                    ConversionUtils.appendPara(paraItems, ficheBlocks);
                    if (!paraItems.isEmpty()) {
                        if (convertFieldKey.equals(FieldKey.SUBTITLE)) {
                            ficheChangeBuilder.setSubtitle(paraItems.get(0));
                        } else if (convertFieldKey.isProp()) {
                            ficheChangeBuilder.setProp(convertFieldKey, paraItems.get(0));
                        } else if (convertFieldKey.isInfo()) {
                            ficheChangeBuilder.appendInfo(convertFieldKey, ConversionUtils.toFicheItems(paraItems));
                        }
                    }
                }
            } 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.appendSection(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;
                }
            }
        }

    }

}
