/* UtilLib - Copyright (c) 2015-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.mapeadores.util.logging;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
import net.mapeadores.util.localisation.LocalisationUtils;
import net.mapeadores.util.localisation.Message;
import net.mapeadores.util.xml.DOMUtils;
import net.mapeadores.util.xml.DomMessages;
import net.mapeadores.util.xml.XMLUtils;
import org.w3c.dom.Element;


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

    private final MessageHandler xmlErrorHandler;

    public SourceLogDOMReader(MessageHandler xmlErrorHandler) {
        this.xmlErrorHandler = xmlErrorHandler;
    }

    public void readLogs(MultiMessageHandler multiMessageHandler, Element element, String xpath) {
        DOMUtils.readChildren(element, new LogConsumer(multiMessageHandler, xpath + "/" + element.getTagName()));
    }

    public void readLog(MessageHandler messageHandler, Element element, String xpath) {
        String uri = element.getAttribute("uri");
        if (uri.length() > 0) {
            xpath = xpath + "/" + element.getTagName() + "[@uri='" + uri + "']";
        } else {
            xpath = xpath + "/" + element.getTagName();
        }
        DOMUtils.readChildren(element, new ListConsumer(messageHandler, xpath));
    }


    private class LogConsumer implements Consumer<Element> {

        private final MultiMessageHandler multiMessageHandler;
        private final String xpath;

        private LogConsumer(MultiMessageHandler multiMessageHandler, String xpath) {
            this.multiMessageHandler = multiMessageHandler;
            this.xpath = xpath;
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            String xpath2 = xpath + "/" + tagName;
            if (tagName.equals("log")) {
                String name = element.getAttribute("name");
                if (name.isEmpty()) {
                    name = element.getAttribute("uri");
                }
                if (name.isEmpty()) {
                    DomMessages.emptyAttribute(xmlErrorHandler, xpath2, "name");
                } else {
                    xpath2 = xpath2 + "[@name='" + name + "']";
                    multiMessageHandler.setCurrentSource(name);
                    DOMUtils.readChildren(element, new MessageConsumer(multiMessageHandler, xpath2));
                }
            } else {
                DomMessages.unknownTagWarning(xmlErrorHandler, xpath2);
            }
        }

    }


    private class MessageConsumer implements Consumer<Element> {

        private final MessageHandler messageHandler;
        private final String xpath;


        private MessageConsumer(MessageHandler messageHandler, String xpath) {
            this.messageHandler = messageHandler;
            this.xpath = xpath;
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            String xpath2 = xpath + "/" + tagName;
            if (tagName.equals("message")) {
                String key = element.getAttribute("key");
                if (key.length() == 0) {
                    DomMessages.emptyAttribute(xmlErrorHandler, xpath2, "key");
                } else {
                    xpath2 = xpath2 + "[@key='" + key + "']";
                    String category = element.getAttribute("category");
                    List<Object> valueList = new ArrayList<Object>();
                    DOMUtils.readChildren(element, new ValuesConsumer(valueList, xpath2));
                    messageHandler.addMessage(category, toMessage(key, valueList));
                }
            } else {
                DomMessages.unknownTagWarning(xmlErrorHandler, xpath2);
            }
        }

    }


    private class ListConsumer implements Consumer<Element> {

        private final MessageHandler messageHandler;
        private final String xpath;


        private ListConsumer(MessageHandler messageHandler, String xpath) {
            this.messageHandler = messageHandler;
            this.xpath = xpath;
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            String xpath2 = xpath + "/" + tagName;
            if (tagName.equals("message")) {
                String key = element.getAttribute("key");
                if (key.length() == 0) {
                    DomMessages.emptyAttribute(xmlErrorHandler, xpath2, "key");
                } else {
                    xpath2 = xpath2 + "[@key='" + key + "']";
                    String category = element.getAttribute("category");
                    List<Object> valueList = new ArrayList<Object>();
                    DOMUtils.readChildren(element, new ValuesConsumer(valueList, xpath2));
                    messageHandler.addMessage(category, toMessage(key, valueList));
                }
            } else {
                DomMessages.unknownTagWarning(xmlErrorHandler, xpath2);
            }
        }

    }


    private class ValuesConsumer implements Consumer<Element> {

        private final List<Object> list;
        private final String xpath;


        private ValuesConsumer(List<Object> list, String xpath) {
            this.list = list;
            this.xpath = xpath;
        }

        @Override
        public void accept(Element element) {
            String tagName = element.getTagName();
            String xpath2 = xpath + "/" + tagName;
            if (tagName.equals("value")) {
                String data = XMLUtils.getData(element);
                try {
                    Integer itg = Integer.parseInt(data);
                    list.add(itg);
                } catch (NumberFormatException nfe) {
                    list.add(data);
                }
            } else {
                DomMessages.unknownTagWarning(xmlErrorHandler, xpath2);
            }
        }

    }

    private static Message toMessage(String key, List<Object> valueList) {
        int size = valueList.size();
        if (size == 0) {
            return LocalisationUtils.toMessage(key);
        } else {
            return LocalisationUtils.toMessage(key, valueList.toArray(new Object[size]));
        }
    }


}
