/*
 * @author Ranides Atterwim <ranides@gmail.com>
 * @copyright Ranides Atterwim
 * @license WTFPL
 * @url http://ranides.net/projects/assira
 */

package net.ranides.assira.xml;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.net.URI;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import net.ranides.assira.collection.query.CQueryBuilder;
import net.ranides.assira.functional.CheckedSupplier;
import net.ranides.assira.trace.ExceptionUtils;
import net.ranides.assira.xml.impl.CElements;
import net.ranides.assira.xml.impl.W3Element;
import org.w3c.dom.Node;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

/**
 *
 * @author Ranides Atterwim <ranides@gmail.com>
 */
@SuppressWarnings("PMD.MethodNameRules")
public final class XMLQuery {
    
    public static final XMLElements $true = $($("<true/>"));
    
    public static final XMLElements $false = new CElements(CQueryBuilder.empty());
    
    private XMLQuery() {
        /* utility class */
    }

    public static XMLElement $(Node doc) {
        return W3Element.wrap(doc);
    }
    
    public static XMLElement $(String doc) {
        return $(new StringReader(doc));
    }
    
    public static XMLElement $(File doc) {
        return $(() -> W3Element.wrap(builder().parse(doc)));
    }
    
    public static XMLElement $(URI doc) {
        return $(() -> W3Element.wrap(builder().parse(doc.toString())));
    }
    
    public static XMLElement $(Reader doc) {
        return $(() -> W3Element.wrap(builder().parse(new InputSource(doc))));
    }
    
    public static XMLElement $(InputStream doc) {
        return $(() -> W3Element.wrap(builder().parse(new InputSource(doc))));
    }
    
    private static XMLElement $(CheckedSupplier<XMLElement> supplier) {
        try {
            return supplier.get();
        } catch (SAXException | ParserConfigurationException | IOException cause) {
            throw new XMLException(cause);
        } catch(Exception cause) {
            throw ExceptionUtils.rethrow(cause);
        }
    }
    
    public static XMLElements $(XMLElements... elements) {
        return new CElements(CQueryBuilder.fromArray(elements).unfold(e -> e.stream()));
    }
    
    public static XMLElements $(XMLElement... elements) {
        return new CElements(CQueryBuilder.fromArray(elements));
    }
    
    private static DocumentBuilder builder() throws ParserConfigurationException {
        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
        factory.setNamespaceAware(false);
        return factory.newDocumentBuilder();
    }
}
