/* BdfServer_Multi - Copyright (c) 2023 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.multi.tools.dom;

import fr.exemole.bdfserver.multi.api.central.CentralUserEditor;
import java.text.ParseException;
import java.util.Locale;
import java.util.function.Consumer;
import net.fichotheque.FichothequeConstants;
import net.mapeadores.util.attr.Attribute;
import net.mapeadores.util.attr.AttributeUtils;
import net.mapeadores.util.attr.Attributes;
import net.mapeadores.util.attr.AttributesBuilder;
import net.mapeadores.util.localisation.Lang;
import net.mapeadores.util.localisation.LangPreference;
import net.mapeadores.util.localisation.LangPreferenceBuilder;
import net.mapeadores.util.localisation.LangsUtils;
import net.mapeadores.util.logging.MessageHandler;
import net.mapeadores.util.models.EmailCore;
import net.mapeadores.util.models.EmailCoreUtils;
import net.mapeadores.util.models.PersonCore;
import net.mapeadores.util.models.PersonCoreUtils;
import net.mapeadores.util.xml.DOMUtils;
import net.mapeadores.util.xml.DomMessages;
import org.w3c.dom.Element;


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

    private final CentralUserEditor centralUserEditor;
    private final MessageHandler messageHandler;

    public CentralUserDOMReader(CentralUserEditor centralUserEditor, MessageHandler messageHandler) {
        this.centralUserEditor = centralUserEditor;
        this.messageHandler = messageHandler;
    }

    public void read(Element element) {
        checkStatus(element);
        RootConsumer rootConsumer = new RootConsumer("/" + element.getTagName());
        DOMUtils.readChildren(element, rootConsumer);
        rootConsumer.flush();
    }

    private void checkStatus(Element element) {
        String statusAttr = element.getAttribute("status");
        String status = FichothequeConstants.ACTIVE_STATUS;
        if (statusAttr.isEmpty()) {
            String active = element.getAttribute("active");
            switch (active) {
                case "false":
                    status = FichothequeConstants.INACTIVE_STATUS;
                    break;

            }
        } else {
            try {
                status = FichothequeConstants.checkRedacteurStatus(statusAttr);
            } catch (IllegalArgumentException iae) {

            }
        }
        centralUserEditor.setStatus(status);
    }


    private class RootConsumer implements Consumer<Element> {

        private final AttributesBuilder attributesBuilder;
        private final String parentXpath;
        private final LangPreferenceBuilder langPreferenceBuilder = new LangPreferenceBuilder();
        private Lang workingLang = null;
        private Locale formatLocale = null;


        private RootConsumer(String parentXpath) {
            this.parentXpath = parentXpath;
            this.attributesBuilder = new AttributesBuilder();
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            String xpath = parentXpath + "/" + tagName;
            switch (tagName) {
                case "attr": {
                    AttributeUtils.readAttrElement(attributesBuilder, element, messageHandler, xpath);
                    break;
                }
                case "password": {
                    String password = DOMUtils.readSimpleElement(element);
                    centralUserEditor.setEncryptedPassword(password);
                    break;
                }
                case "email": {
                    EmailCore emailCore = null;
                    try {
                        emailCore = toEmailCore(element);
                    } catch (ParseException iae) {
                        DomMessages.wrongAttributeValue(messageHandler, tagName, "addr-spec", element.getAttribute("addr-spec"));
                    }
                    centralUserEditor.setEmail(emailCore);
                    break;
                }
                case "format-locale": {
                    try {
                        Lang formatLocaleLang = Lang.parse(DOMUtils.readSimpleElement(element));
                        this.formatLocale = formatLocaleLang.toLocale();
                    } catch (ParseException lie) {

                    }
                    break;
                }
                case "lang": {
                    try {
                        workingLang = Lang.parse(DOMUtils.readSimpleElement(element));
                    } catch (ParseException pe) {

                    }
                    break;
                }
                case "lang-preference": {
                    LangsUtils.readLangElements(langPreferenceBuilder, element, messageHandler, xpath);
                    break;
                }
                case "person": {
                    PersonCore personCore = toPersonCore(element);
                    centralUserEditor.setPerson(personCore);
                    break;
                }
                default:
                    DomMessages.unknownTagWarning(messageHandler, tagName);
            }
        }

        private void flush() {
            Attributes attributes = attributesBuilder.toAttributes();
            for (Attribute attribute : attributes) {
                centralUserEditor.putAttribute(attribute);
            }
            if (workingLang != null) {
                LangPreference langPreference = null;
                if (!langPreferenceBuilder.isEmpty()) {
                    langPreference = langPreferenceBuilder.toLangPreference();
                }
                centralUserEditor.setLangContext(workingLang, formatLocale, langPreference);
            }
        }

    }

    private static PersonCore toPersonCore(Element element) {
        String surname = element.getAttribute("surname");
        String forename = element.getAttribute("forename");
        String nonlatin = element.getAttribute("nonlatin");
        boolean surnameFirst = false;
        String surnameFirstString = element.getAttribute("surname-first");
        if (surnameFirstString.equals("true")) {
            surnameFirst = true;
        }
        return PersonCoreUtils.toPersonCore(surname, forename, nonlatin, surnameFirst);
    }

    private static EmailCore toEmailCore(Element element) throws ParseException {
        String addrSpec = element.getAttribute("addr-spec");
        String realName = element.getAttribute("real-name");
        if (realName.length() == 0) {
            realName = element.getAttribute("nom-complet");
        }
        return EmailCoreUtils.parse(addrSpec, realName);
    }

}
