package at.procon.eventhub.tachographfilesession.service;

import java.util.HashMap;
import java.util.Map;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import org.w3c.dom.NodeList;

final class XmlExpressionEvaluator {

    private static final XPathFactory XPATH_FACTORY = XPathFactory.newInstance();

    private final ThreadLocal<XPathContext> contexts = ThreadLocal.withInitial(XPathContext::new);

    NodeList nodes(Object node, String expression) {
        try {
            return (NodeList) contexts.get().compile(expression).evaluate(node, XPathConstants.NODESET);
        } catch (XPathExpressionException e) {
            throw new IllegalStateException("Invalid XPath expression: " + expression, e);
        }
    }

    String text(Object node, String expression) {
        try {
            String value = contexts.get().compile(expression).evaluate(node);
            return value == null || value.isBlank() ? null : value.trim();
        } catch (XPathExpressionException e) {
            throw new IllegalStateException("Invalid XPath expression: " + expression, e);
        }
    }

    private static final class XPathContext {
        private final XPath xpath = XPATH_FACTORY.newXPath();
        private final Map<String, XPathExpression> compiledExpressions = new HashMap<>();

        private XPathExpression compile(String expression) {
            return compiledExpressions.computeIfAbsent(expression, key -> {
                try {
                    return xpath.compile(key);
                } catch (XPathExpressionException e) {
                    throw new IllegalStateException("Invalid XPath expression: " + key, e);
                }
            });
        }
    }
}
