/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.ode.bpel.elang.xpath20.compiler;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.xml.namespace.QName;
import javax.xml.transform.TransformerFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;
import javax.xml.xpath.XPathFactoryConfigurationException;

import net.sf.saxon.om.Name11Checker;
import net.sf.saxon.om.NamespaceConstant;
import net.sf.saxon.xpath.XPathEvaluator;
import net.sf.saxon.xpath.XPathFactoryImpl;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.ode.bpel.compiler.api.CompilationException;
import org.apache.ode.bpel.compiler.api.CompilerContext;
import org.apache.ode.bpel.compiler.api.ExpressionCompiler;
import org.apache.ode.bpel.compiler.bom.Expression;
import org.apache.ode.bpel.elang.xpath10.compiler.XPathMessages;
import org.apache.ode.bpel.elang.xpath10.compiler.XslCompilationErrorListener;
import org.apache.ode.bpel.elang.xpath20.obj.OXPath20ExpressionBPEL20;
import org.apache.ode.bpel.obj.OExpression;
import org.apache.ode.bpel.obj.OLValueExpression;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.msg.MessageBundle;
import org.apache.ode.utils.xsl.XslTransformHandler;
import org.w3c.dom.Node;

/**
 * XPath compiler based on the SAXON implementation.
 * @author Matthieu Riou <mriou at apache dot org>
 */
public class XPath20ExpressionCompilerImpl implements ExpressionCompiler {

    protected static final Logger __log = LoggerFactory.getLogger(XPath20ExpressionCompilerBPEL20.class);

    protected String _bpelNS;
    protected QName _qnLinkStatus;
    protected QName _qnVarProp;
    protected QName _qnVarData;
    protected QName _qnXslTransform;

    protected final XPathMessages __msgs = MessageBundle.getMessages(XPathMessages.class);
    protected Map<String, String> _properties = new HashMap<String, String>();
    protected CompilerContext _compilerContext;

    public XPath20ExpressionCompilerImpl(String bpelNS) {
        _bpelNS = bpelNS;
        _qnLinkStatus = new QName(_bpelNS, Constants.EXT_FUNCTION_GETLINKSTATUS);
        _qnVarProp = new QName(_bpelNS, Constants.EXT_FUNCTION_GETVARIABLEPROPERTY);
        _qnVarData = new QName(_bpelNS, Constants.EXT_FUNCTION_GETVARIABLEDATA);
        _qnXslTransform = new QName(_bpelNS, Constants.EXT_FUNCTION_DOXSLTRANSFORM);

        _properties.put("runtime-class", "org.apache.ode.bpel.elang.xpath20.runtime.XPath20ExpressionRuntime");
        TransformerFactory trsf = new net.sf.saxon.TransformerFactoryImpl();
        XslTransformHandler.getInstance().setTransformerFactory(trsf);
    }

    public void setCompilerContext(CompilerContext compilerContext) {
        _compilerContext = compilerContext;
        XslCompilationErrorListener xe = new XslCompilationErrorListener(compilerContext);
        XslTransformHandler.getInstance().setErrorListener(xe);
    }

    /**
     * @see org.apache.ode.bpel.compiler.api.ExpressionCompiler#compileJoinCondition(java.lang.Object)
     */
    public OExpression compileJoinCondition(Object source) throws CompilationException {
        return _compile((Expression) source, true);
    }

    /**
     * @see org.apache.ode.bpel.compiler.api.ExpressionCompiler#compile(java.lang.Object)
     */
    public OExpression compile(Object source) throws CompilationException {
        return _compile((Expression) source, false);
    }

    /**
     * @see org.apache.ode.bpel.compiler.api.ExpressionCompiler#compileLValue(java.lang.Object)
     */
    public OLValueExpression compileLValue(Object source) throws CompilationException {
        return (OLValueExpression) _compile((Expression) source, false);
    }
    
    /**
     * @see org.apache.ode.bpel.compiler.api.ExpressionCompiler#compile(java.lang.Object)
     */
    private OExpression _compile(org.apache.ode.bpel.compiler.bom.Expression xpath, boolean isJoinCondition)
            throws CompilationException {
        OXPath20ExpressionBPEL20 oexp = new OXPath20ExpressionBPEL20(_compilerContext.getOProcess(), _qnVarData,
                _qnVarProp, _qnLinkStatus, _qnXslTransform, isJoinCondition);
        oexp.setNamespaceCtx(_compilerContext.tryCacheNamespaceContext(xpath.getNamespaceContext()));
        doJaxpCompile(oexp, xpath);
        return oexp;
    }

    private void doJaxpCompile(OXPath20ExpressionBPEL20 out, Expression source) throws CompilationException {
        String xpathStr;
        Node node = source.getExpression();
        if (node == null) {
            throw new CompilationException(__msgs.errEmptyExpression(source.getURI(), new QName(source.getElement().getNamespaceURI(), source.getElement().getNodeName())));
        }
        if (node.getNodeType() != Node.TEXT_NODE && node.getNodeType() != Node.CDATA_SECTION_NODE) {
            throw new CompilationException(__msgs.errUnexpectedNodeTypeForXPath(DOMUtils.domToString(node)));
        }
        xpathStr = node.getNodeValue();
        xpathStr = xpathStr.trim();
        if (xpathStr.length() == 0) {
            throw new CompilationException(__msgs.warnXPath20Syntax(DOMUtils.domToString(node), "empty string"));
        }

        out.setXpath(xpathStr);
        try {
            __log.debug("Compiling expression " + xpathStr);
            XPathFactory xpf = new XPathFactoryImpl();
            JaxpFunctionResolver funcResolver = new JaxpFunctionResolver(
                    _compilerContext, out, source.getNamespaceContext(), _bpelNS);
            JaxpVariableResolver varResolver = new JaxpVariableResolver(_compilerContext, out);
            XPath xpe = xpf.newXPath();
            xpe.setXPathFunctionResolver(funcResolver);
            xpe.setXPathVariableResolver(varResolver);
            xpe.setNamespaceContext(source.getNamespaceContext());
            XPathExpression expr = xpe.compile(xpathStr);
            // evaluate the expression so as to initialize the variables
            try {
                expr.evaluate(node);
            } catch (XPathExpressionException xpee) {
                // swallow errors caused by uninitialized variable
            }
            for (String varExpr : extractVariableExprs(xpathStr)) {
                expr = xpe.compile(varExpr);
                try {
                    expr.evaluate(node);
                } catch (XPathExpressionException xpee) {
                    // swallow errors caused by uninitialized variable
                }
            }
            for (String functionExpr : extractFunctionExprs(xpathStr)) {
                expr = xpe.compile(functionExpr);
                try {
                    expr.evaluate(node);
                } catch (XPathExpressionException xpee) {
                    // swallow errors caused by uninitialized variable
                }
            }
        } catch (XPathExpressionException e) {
            __log.debug("",e);
            __log.info("Couldn't validate properly expression " + xpathStr);
        } catch (WrappedResolverException wre) {
            if (wre._compilationMsg != null)
                throw new CompilationException(wre._compilationMsg, wre);
            if (wre.getCause() instanceof CompilationException)
                throw (CompilationException) wre.getCause();
            throw wre;
        }
    }

    /**
     * Returns the list of variable references in the given XPath expression
     * that may not have been resolved properly, which is the case especially
     * if the expression contains a function, which short circuited the evaluation.
     *
     * @param xpathStr
     * @return list of variable expressions that may not have been resolved properly
     */
    private List<String> extractVariableExprs(String xpathStr) {
        ArrayList<String> variableExprs = new ArrayList<String>();
        int firstVariable = xpathStr.indexOf("$"),
            lastVariable = xpathStr.lastIndexOf("$"),
            firstFunction = xpathStr.indexOf("(");
        StringBuffer variableExpr = new StringBuffer();
        if ((firstVariable > 0 && // the xpath references a variable
                firstFunction > 0) || // the xpath contains a function
            (firstVariable < lastVariable)) { // the xpath references multiple variables
            // most likely, the variable reference has not been resolved, so make that happen
            boolean quoted = false, doubleQuoted = false, variable = false;
            Name11Checker nameChecker = Name11Checker.getInstance();
            for (int index = 0; index < xpathStr.length(); index++) {
                char ch = xpathStr.charAt(index);
                if (ch == '\''){
                    quoted = !quoted;
                }
                if (ch == '\"') {
                    doubleQuoted = !doubleQuoted;
                }
                if (quoted || doubleQuoted){
                    continue;
                }
                if (ch == '$') {
                    variable = true;
                    variableExpr.setLength(0);
                    variableExpr.append(ch);
                } else {
                    if (variable) {
                        variableExpr.append(ch);
                        // in the name is qualified, don't check if its a qname when we're at the ":" character
                        if (ch == ':') {
                            continue;
                        }
                        if (index == xpathStr.length() ||
                                !nameChecker.isQName(variableExpr.substring(1))) {
                            variable = false;
                            variableExpr.setLength(variableExpr.length() - 1);
                            variableExprs.add(variableExpr.toString());
                            variableExpr.setLength(0);
                        }
                    }
                }
            }
            if (variableExpr.length() > 0) {
                variableExprs.add(variableExpr.toString());
            }
        }
        return variableExprs;
    }

    /**
     * Returns the list of function references in the given XPath expression
     * that may not have been resolved properly, which is the case especially
     * if the expression contains a preceding function, which short circuited the evaluation.
     *
     * @param xpathStr
     * @return list of function expressions that may not have been resolved properly
     */
    private List<String> extractFunctionExprs(String xpathStr) {
        ArrayList<String> functionExprs = new ArrayList<String>();
        // Match the prefix : function name ( all contents except the ) and the closing )'s that may occur
//        final String FUNCTION_REGEX = "\\w+:\\w+\\([.[^\\)]]*\\)*";
        final String FUNCTION_REGEX = "(\\w+:)?\\w+\\((.+)?\\)";
        int firstFunction = xpathStr.indexOf("("),
            lastFunction = xpathStr.lastIndexOf("(");
        if ((firstFunction > 0 && firstFunction < lastFunction)) {
            Pattern regex = Pattern.compile(FUNCTION_REGEX);
            Matcher matcher = regex.matcher(xpathStr);

            while (matcher.find()) {
                String function = matcher.group();
                functionExprs.add(function);
            }
        }
        return functionExprs;
    }

    public Map<String, String> getProperties() {
        return _properties;
    }

}
