package de.votian.services.service;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.InputSource;

import javax.xml.XMLConstants;
import javax.xml.parsers.DocumentBuilderFactory;
import java.io.StringReader;

final class LegacyXmlXmlParsing {

    private LegacyXmlXmlParsing() {
    }

    static Element parseRequest(String xmlRequest, String requestTag) throws Exception {
        if (xmlRequest == null || xmlRequest.isBlank()) {
            throw new LegacyXmlRequestException("100", "Der Wert entspricht nicht dem geforderten Typ bzw. den Validitaetsbedingungen.");
        }
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
        factory.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
        factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
        factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
        factory.setXIncludeAware(false);
        factory.setExpandEntityReferences(false);
        Document document = factory.newDocumentBuilder().parse(new InputSource(new StringReader(xmlRequest)));
        Element root = document.getDocumentElement();
        if (root == null || !"xml".equalsIgnoreCase(root.getTagName())) {
            throw new LegacyXmlRequestException("100", "Der Wert entspricht nicht dem geforderten Typ bzw. den Validitaetsbedingungen.");
        }
        Element request = child(root, requestTag);
        if (request == null) {
            throw new LegacyXmlRequestException("100", "Der Wert entspricht nicht dem geforderten Typ bzw. den Validitaetsbedingungen.");
        }
        return request;
    }

    static Element child(Element parent, String tagName) {
        if (parent == null || tagName == null) {
            return null;
        }
        NodeList nodes = parent.getChildNodes();
        for (int i = 0; i < nodes.getLength(); i++) {
            Node node = nodes.item(i);
            if (node instanceof Element element && tagName.equalsIgnoreCase(element.getTagName())) {
                return element;
            }
        }
        return null;
    }

    static String text(Element parent, String tagName) {
        Element child = child(parent, tagName);
        return child != null && child.getTextContent() != null ? child.getTextContent().trim() : "";
    }
}
