/*
 * 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.xquery10.compiler;

import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.namespace.QName;
import javax.xml.transform.Source;
import javax.xml.transform.TransformerFactory;
import javax.xml.xquery.XQConnection;
import javax.xml.xquery.XQConstants;
import javax.xml.xquery.XQDataSource;
import javax.xml.xquery.XQException;
import javax.xml.xquery.XQItemType;
import javax.xml.xquery.XQPreparedExpression;
import javax.xml.xquery.XQSequence;
import javax.xml.xquery.XQStaticContext;

import net.sf.saxon.Configuration;
import net.sf.saxon.om.Validation;
import net.sf.saxon.xqj.SaxonXQConnection;
import net.sf.saxon.xqj.SaxonXQDataSource;

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.compiler.Constants;
import org.apache.ode.bpel.elang.xpath20.compiler.JaxpFunctionResolver;
import org.apache.ode.bpel.elang.xpath20.compiler.JaxpVariableResolver;
import org.apache.ode.bpel.elang.xpath20.compiler.WrappedResolverException;
import org.apache.ode.bpel.elang.xquery10.obj.OXQuery10ExpressionBPEL20;
import org.apache.ode.bpel.obj.OConstantVarType;
import org.apache.ode.bpel.obj.OElementVarType;
import org.apache.ode.bpel.obj.OExpression;
import org.apache.ode.bpel.obj.OLValueExpression;
import org.apache.ode.bpel.obj.OMessageVarType;
import org.apache.ode.bpel.obj.OScope;
import org.apache.ode.bpel.obj.OVarType;
import org.apache.ode.bpel.obj.OXsdTypeVarType;
import org.apache.ode.bpel.obj.OMessageVarType.Part;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.NSContext;
import org.apache.ode.utils.Namespaces;
import org.apache.ode.utils.msg.MessageBundle;
import org.apache.ode.utils.xsl.XslTransformHandler;
import org.apache.xml.utils.XMLChar;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

/**
 * XQuery compiler based on the SAXON implementation.
 */
public class XQuery10ExpressionCompilerImpl implements ExpressionCompiler {

    protected static final Logger __log = LoggerFactory.getLogger(XQuery10ExpressionCompilerImpl.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 XQuery10ExpressionCompilerImpl(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.xquery10.runtime.XQuery10ExpressionRuntime");
        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 xquery, boolean isJoinCondition)
            throws CompilationException {
        OXQuery10ExpressionBPEL20 oexp = new OXQuery10ExpressionBPEL20(_compilerContext.getOProcess(), _qnVarData,
                _qnVarProp, _qnLinkStatus, _qnXslTransform, isJoinCondition);
        oexp.setNamespaceCtx(xquery.getNamespaceContext());
        doJaxpCompile(oexp, xquery);
        return oexp;
    }

    private void doJaxpCompile(OXQuery10ExpressionBPEL20 out, Expression source) throws CompilationException {
        String xqueryStr;
        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.ELEMENT_NODE &&
                node.getNodeType() != Node.CDATA_SECTION_NODE) {
            throw new CompilationException(__msgs.errUnexpectedNodeTypeForXPath(DOMUtils.domToString(node)));
        }
        xqueryStr = DOMUtils.domToString(node);
        xqueryStr = xqueryStr.trim();
        if (xqueryStr.length() == 0) {
            throw new CompilationException(__msgs.warnXPath20Syntax(DOMUtils.domToString(node), "empty string"));
        }

        try {
            XQDataSource xqds = new SaxonXQDataSource(new Configuration());
            XQConnection xqconn = xqds.getConnection();

            __log.debug("Compiling expression " + xqueryStr);
            Configuration configuration = ((SaxonXQConnection) xqconn).getConfiguration();
            configuration.setAllNodesUntyped(true);
            configuration.setHostLanguage(Configuration.XQUERY);

            XQStaticContext staticContext = xqconn.getStaticContext();
            JaxpFunctionResolver funcResolver = new JaxpFunctionResolver(
                    _compilerContext, out, source.getNamespaceContext(), _bpelNS);
            JaxpVariableResolver variableResolver = new JaxpVariableResolver(
                    _compilerContext, out);

            XQueryDeclarations declarations = new XQueryDeclarations();
            NSContext nsContext = source.getNamespaceContext();
            Set<String> prefixes = nsContext.getPrefixes();
            if (!nsContext.getUriSet().contains(Namespaces.ODE_EXTENSION_NS)) {
                nsContext.register("ode", Namespaces.ODE_EXTENSION_NS);
            }
            for (String prefix : prefixes) {
                String uri = nsContext.getNamespaceURI(prefix);
                staticContext.declareNamespace(prefix, uri);
                if ("".equals(prefix)) {
                    declarations.declareDefaultElementNamespace(uri);
                } else if ("bpws".equals(prefix)) {
                    declarations.declareNamespace("bpws", "java:" + Constants.XQUERY_FUNCTION_HANDLER_COMPILER);
                } else {
                    declarations.declareNamespace(prefix, uri);
                }
            }
            declarations.declareVariable(
                    getQName(nsContext, Namespaces.ODE_EXTENSION_NS, "pid"),
                    getQName(nsContext, Namespaces.XML_SCHEMA, "integer"));
//            Map<URI, Source> schemaDocuments = _compilerContext.getSchemaSources();
//            for (URI schemaUri : schemaDocuments.keySet()) {
//            	Source schemaSource = schemaDocuments.get(schemaUri);
//            	// Don't add schema sources, since our Saxon library is not schema-aware.
//            	// configuration.addSchemaSource(schemaSource);
//            }
            configuration.setSchemaValidationMode(Validation.SKIP);
            List<OScope.Variable> variables = _compilerContext.getAccessibleVariables();
            Map<QName, QName> variableTypes = new HashMap<QName, QName>();
            for (String variableName : getVariableNames(xqueryStr)) {
                OScope.Variable variable = getVariable(variables, variableName);
                if (variable == null) {
                    continue;
                }
                OVarType type = variable.getType();
                QName nameQName = getNameQName(variableName);
                QName typeQName = getTypeQName(variableName, type);
                variableTypes.put(nameQName, typeQName);
                String prefix = typeQName.getPrefix();
                if (prefix == null || "".equals(prefix.trim())) {
                    prefix = getPrefixForUri(nsContext, typeQName.getNamespaceURI());
                }
                // don't declare typed variables, as our engine is not schema-aware
                // declarations.declareVariable(variable.name, typeQName);
                declarations.declareVariable(variableName);
            }

            // Add implicit declarations as prolog to the user-defined XQuery
            out.setXquery((declarations.toString()) + xqueryStr);

            // Check the XQuery for compilation errors
            xqconn.setStaticContext(staticContext);
            XQPreparedExpression exp = xqconn.prepareExpression(out.getXquery());

            // Pre-evaluate variables and functions by executing query
            node.setUserData(XQuery10BpelFunctions.USER_DATA_KEY_FUNCTION_RESOLVER,
                    funcResolver, null);
            exp.bindItem(XQConstants.CONTEXT_ITEM,
                    xqconn.createItemFromNode(node, xqconn.createNodeType()));
            // Bind external variables to dummy runtime values
            for (QName variable : exp.getAllUnboundExternalVariables()) {
                QName typeQName = variableTypes.get(variable);
                Object value = variableResolver.resolveVariable(variable);
                if (typeQName != null) {
                    if (value.getClass().getName().startsWith("java.lang")) {
                        exp.bindAtomicValue(variable, value.toString(),
                                xqconn.createAtomicType(XQItemType.XQBASETYPE_ANYATOMICTYPE));
                    } else if (value instanceof Node) {
                        exp.bindNode(variable, (Node) value, xqconn.createNodeType());
                    } else if (value instanceof NodeList) {
                        NodeList nodeList = (NodeList) value;
                        ArrayList nodeArray = new ArrayList();
                        for (int i = 0; i < nodeList.getLength(); i++) {
                            nodeArray.add(nodeList.item(i));
                        }
                        XQSequence sequence = xqconn.createSequence(nodeArray.iterator());
                        exp.bindSequence(variable, sequence);
                    }
                }
            }
            // evaluate the expression so as to initialize the variables
            try {
                exp.executeQuery();
            } catch (XQException xpee) {
                // swallow errors caused by uninitialized variables
            } finally {
                // reset the expression's user data, in order to avoid
                // serializing the function resolver in the compiled bpel file.
                if (node != null) {
                    node.setUserData(XQuery10BpelFunctions.USER_DATA_KEY_FUNCTION_RESOLVER, null, null);
                }
            }
        } catch (XQException xqe) {
            __log.debug("",xqe);
            __log.info("Couldn't validate properly expression " + xqueryStr);
            throw new CompilationException(__msgs.errXQuery10Syntax(xqueryStr, "Couldn't validate XQuery expression"));
        } catch (WrappedResolverException wre) {
            if (wre._compilationMsg != null)
                throw new CompilationException(wre._compilationMsg, wre);
            if (wre.getCause() instanceof CompilationException)
                throw (CompilationException) wre.getCause();
            throw wre;
        }
    }

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

    private String getQName(NSContext nsContext, String uri, String localPart) {
        String prefix = getPrefixForUri(nsContext, uri);
        return (prefix == null ? localPart : (prefix + ":" + localPart));
    }

    private String getPrefixForUri(NSContext nsContext, String uri) {
        Set<String> prefixes = nsContext.getPrefixes();
        for (String prefix : prefixes) {
            String anUri = (nsContext.getNamespaceURI(prefix));
            if (anUri != null && anUri.equals(uri)) {
                return prefix;
            }
        }
        return null;
    }

    protected static Collection<String> getVariableNames(String xquery) {
        Collection<String> variableNames = new LinkedHashSet<String>();
        for (int index = xquery.indexOf("$"); index != -1; index = xquery.indexOf("$")) {
            StringBuilder variableName = new StringBuilder();
            index++;
            while(index < xquery.length() && XMLChar.isNCName(xquery.charAt(index))) {
                variableName.append(xquery.charAt(index++));
            }
            variableNames.add(variableName.toString());
            xquery = xquery.substring(index);
        }
        return variableNames;
    }

    private OScope.Variable getVariable(List<OScope.Variable> variables, String variableName) {
        String declaredVariable = getVariableDeclaredName(variableName);
        for (OScope.Variable variable : variables) {
            if (variable.getName().equals(declaredVariable)) {
                return variable;
            }
        }
        return null;
    }

    private String getVariableDeclaredName(String variableReference) {
        int dotIndex = variableReference.indexOf(".");
        return dotIndex >= 0 ? variableReference.substring(0, dotIndex) : variableReference;
    }

    private String getVariablePartName(String variableReference) {
        int dotIndex = variableReference.indexOf(".");
        return dotIndex >= 0 ? variableReference.substring(dotIndex + 1) : "";
    }

    private QName getNameQName(String variableName) {
        String prefix = null, localName = null;;
        int colonIndex = variableName.indexOf(":");
        if (colonIndex >= 0) {
            prefix = variableName.substring(0, colonIndex);
            localName = variableName.substring(colonIndex + 1);
        } else {
            prefix = "";
            localName = variableName;
        }
        return new QName(prefix, localName);
    }

    private QName getTypeQName(String variableName, OVarType type) {
        QName typeQName = null;
        if (type instanceof OConstantVarType) {
            typeQName = new QName(Namespaces.XML_SCHEMA, "string", "xs");
        } else if (type instanceof OElementVarType) {
            typeQName = ((OElementVarType) type).getElementType();
        } else if (type instanceof OMessageVarType) {
            Part part = ((OMessageVarType) type).getParts().get(getVariablePartName(variableName));
            if (part != null) {
                typeQName = getTypeQName(variableName, part.getType());
            }
        } else if (type instanceof OXsdTypeVarType) {
            typeQName = ((OXsdTypeVarType) type).getXsdType();
        }
        return typeQName;
    }

    private static class XQueryDeclarations {
        StringBuffer declarations = new StringBuffer();

        public XQueryDeclarations() {}

        public void declareVariable(String name, QName type) {
            declareVariable(name, type.getPrefix() + ":" + type.getLocalPart());
        }

        public void declareVariable(String name, String type) {
            declarations.append("declare variable ")
                .append("$")
                .append(name)
                .append(" as ")
                .append(type)
                .append(" external ")
                .append(";\n");
        }

        public void declareVariable(String name) {
            declarations.append("declare variable ")
                .append("$")
                .append(name)
                .append(" external ")
                .append(";\n");
        }

        public void declareNamespace(String prefix, String uri) {
            declarations.append("declare namespace ")
                .append(prefix)
                .append("=")
                .append("\"" + uri + "\"")
                .append(";\n");
        }

        public void declareDefaultElementNamespace(String uri) {
            declarations.append("declare default element namespace ")
                .append("\"" + uri + "\"")
                .append(";\n");
        }

        public String toString() {
            return declarations.toString();
        }
    }
}
