/* BdfServer_DirectoryStorage - Copyright (c) 2022-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.storage.directory.tools;

import fr.exemole.bdfserver.api.storage.BdfStorageException;
import fr.exemole.bdfserver.conf.ConfDirs;
import fr.exemole.bdfserver.storage.directory.StorageDirectoryUtils;
import fr.exemole.bdfserver.storage.directory.bdfdata.BdfdataConstants;
import fr.exemole.bdfserver.storage.directory.bdfdata.BdfdataStorageFileCatalog;
import fr.exemole.bdfserver.tools.storage.StorageFile;
import java.text.ParseException;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.function.Consumer;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.text.Label;
import net.mapeadores.util.text.LabelChangeBuilder;
import net.mapeadores.util.text.LabelUtils;
import net.mapeadores.util.text.Labels;
import net.mapeadores.util.text.Phrases;
import net.mapeadores.util.text.PhrasesBuilder;
import net.mapeadores.util.xml.DOMUtils;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import fr.exemole.bdfserver.storage.directory.StorageDirectory;


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

    private MetadataExtractor() {

    }

    public static Result getPhrases(ConfDirs confDirs) {
        StorageDirectory storageDirectoriy = StorageDirectoryUtils.toStorageDirectory(confDirs, BdfdataConstants.ROOT);
        StorageFile storageFile = BdfdataStorageFileCatalog.fichothequeMetadata(storageDirectoriy);
        if (!storageFile.exists()) {
            return null;
        }
        try {
            ResultBuilder resultBuilder = new ResultBuilder();
            Document document = storageFile.readDocument();
            DOMUtils.readChildren(document.getDocumentElement(), new RootConsumer(resultBuilder));
            return resultBuilder.toResult();
        } catch (BdfStorageException bse) {
            return null;
        }
    }


    public static class Result {

        private final Labels titleLabels;
        private final Phrases phrases;

        private Result(Labels titleLabels, Phrases phrases) {
            this.titleLabels = titleLabels;
            this.phrases = phrases;
        }

        public Labels getTitleLabels() {
            return titleLabels;
        }

        public Phrases getPhrases() {
            return phrases;
        }

    }


    private static class ResultBuilder {

        private final Map<Lang, Label> labelMap = new LinkedHashMap<Lang, Label>();
        private final PhrasesBuilder phrasesBuilder = new PhrasesBuilder();

        private ResultBuilder() {

        }

        private void addLabel(Label label) {
            labelMap.put(label.getLang(), label);
        }

        private LabelChangeBuilder getPhraseBuilder(String name) {
            return phrasesBuilder.getPhraseBuilder(name);
        }

        private Result toResult() {
            return new Result(LabelUtils.toLabels(labelMap), phrasesBuilder.toPhrases());
        }

    }


    private static class RootConsumer implements Consumer<Element> {

        private final ResultBuilder resultBuilder;

        private RootConsumer(ResultBuilder resultBuilder) {
            this.resultBuilder = resultBuilder;
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            if (tagName.equals("label")) {
                try {
                    Label label = LabelUtils.readLabel(element);
                    if (label != null) {
                        resultBuilder.addLabel(label);
                    }
                } catch (ParseException pe) {
                }
            } else if (tagName.equals("phrase")) {
                String name = element.getAttribute("name");
                if (!name.isEmpty()) {
                    DOMUtils.readChildren(element, new PhraseLabelConsumer(resultBuilder.getPhraseBuilder(name)));
                }
            } else if (tagName.equals("attr")) {
            }

        }

    }


    private static class PhraseLabelConsumer implements Consumer<Element> {

        private final LabelChangeBuilder labelChangeBuilder;

        private PhraseLabelConsumer(LabelChangeBuilder labelChangeBuilder) {
            this.labelChangeBuilder = labelChangeBuilder;
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            if (tagName.equals("label")) {
                try {
                    Label label = LabelUtils.readLabel(element);
                    if (label != null) {
                        labelChangeBuilder.putLabel(label);
                    }
                } catch (ParseException pe) {

                }
            }
        }

    }

}
