/*
 * 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.xpath10.runtime;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.namespace.QName;
import javax.xml.transform.dom.DOMSource;

import net.sf.saxon.dom.NodeWrapper;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.ode.bpel.common.FaultException;
import org.apache.ode.bpel.elang.XslRuntimeUriResolver;
import org.apache.ode.bpel.elang.xpath10.obj.OXPath10Expression;
import org.apache.ode.bpel.elang.xpath10.obj.OXPath10ExpressionBPEL20;
import org.apache.ode.bpel.explang.EvaluationContext;
import org.apache.ode.bpel.explang.EvaluationException;
import org.apache.ode.bpel.obj.OLink;
import org.apache.ode.bpel.obj.OMessageVarType;
import org.apache.ode.bpel.obj.OProcess;
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.OXslSheet;
import org.apache.ode.utils.DOMUtils;
import org.apache.ode.utils.xsl.XslTransformHandler;
import org.jaxen.Context;
import org.jaxen.Function;
import org.jaxen.FunctionCallException;
import org.jaxen.FunctionContext;
import org.jaxen.UnresolvableException;
import org.jaxen.VariableContext;
import org.jaxen.XPathFunctionContext;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;


/**
 * Implementation of the various JAXEN evaluation contexts in terms of the
 * {@link EvaluationContext}.
 */
class JaxenContexts implements FunctionContext, VariableContext {
    private static final Log __log = LogFactory.getLog(JaxenContexts.class);

    /** Static, thread-safe singleton implementing default XPath functions */
    private static final FunctionContext __defaultXPathFunctions = XPathFunctionContext.getInstance();
    
    private static final QName BOOLEAN = new QName("http://www.w3.org/2001/XMLSchema", "boolean");
    private static final QName BYTE = new QName("http://www.w3.org/2001/XMLSchema", "byte");
    private static final QName INT = new QName("http://www.w3.org/2001/XMLSchema", "int");
    private static final QName INTEGER = new QName("http://www.w3.org/2001/XMLSchema", "integer");
    private static final QName LONG = new QName("http://www.w3.org/2001/XMLSchema", "long");
    private static final QName SHORT = new QName("http://www.w3.org/2001/XMLSchema", "short");
    private static final QName UNSIGNED_INT = new QName("http://www.w3.org/2001/XMLSchema", "unsignedInt");
    private static final QName UNSIGNED_SHORT = new QName("http://www.w3.org/2001/XMLSchema", "unsignedShort");
    private static final QName UNSIGNED_BYTE = new QName("http://www.w3.org/2001/XMLSchema", "unsignedByte");
    private static final QName DECIMAL = new QName("http://www.w3.org/2001/XMLSchema", "decimal");
    private static final QName FLOAT = new QName("http://www.w3.org/2001/XMLSchema", "float");
    private static final QName DOUBLE = new QName("http://www.w3.org/2001/XMLSchema", "double");


    private OXPath10Expression _oxpath;
    private EvaluationContext _xpathEvalCtx;
    private Function _getVariableProperty;
    private Function _getVariableData;
    private Function _getLinkStatus;
    private Function _doXslTransform;
    private Map _extensionFunctions;

    public JaxenContexts(OXPath10Expression oxpath,
                         Map extensionFunctions,
                         EvaluationContext xpathEvalCtx) {
        _oxpath = oxpath;
        _xpathEvalCtx = xpathEvalCtx;
        _extensionFunctions = extensionFunctions;
        _getVariableProperty = new BpelVariablePropertyFunction();
        _getVariableData = new BpelVariableDataFunction();
        _getLinkStatus = new GetLinkStatusFunction();
        _doXslTransform = new DoXslTransformFunction();
    }

    /**
     * @see org.jaxen.FunctionContext#getFunction(java.lang.String,
     *      java.lang.String, java.lang.String)
     */
    public Function getFunction(String namespaceURI, String prefix,
                                String localName)
            throws UnresolvableException {
        if (__log.isDebugEnabled()) {
            __log.debug("getFunction(" + namespaceURI + "," + prefix + ","
                    + localName);
        }

        if ((namespaceURI != null)) {
            QName fnQName = new QName(namespaceURI, localName);

            if (fnQName.equals(_oxpath.getQname_getVariableProperty()))
                return _getVariableProperty;
            if (fnQName.equals(_oxpath.getQname_getVariableData()))
                return _getVariableData;
            if (fnQName.equals(_oxpath.getQname_getLinkStatus()))
                return _getLinkStatus;
            if (_oxpath instanceof OXPath10ExpressionBPEL20) {
                OXPath10ExpressionBPEL20 oxpath20 = (OXPath10ExpressionBPEL20) _oxpath;
                if (fnQName.equals(oxpath20.getQname_doXslTransform())) {
                    return _doXslTransform;
                }
            }
            Function f = (Function)_extensionFunctions.get(localName);

            if (f != null) {
                return f;
            }
        }

        // Defer to the default XPath context.
        return __defaultXPathFunctions.getFunction(null, prefix, localName);
    }

    /**
     * @see org.jaxen.VariableContext#getVariableValue(java.lang.String,
     *      java.lang.String, java.lang.String)
     */
    public Object getVariableValue(String namespaceURI, String prefix,
                                   String localName)
            throws UnresolvableException {
        if(!(_oxpath instanceof OXPath10ExpressionBPEL20)){
            throw new IllegalStateException("XPath variables not supported for bpel 1.1");
        }

        // Custom variables
        if ("ode".equals(prefix)) {
            if ("pid".equals(localName)) {
                return _xpathEvalCtx.getProcessId();
            }
        }

        OXPath10ExpressionBPEL20 expr = (OXPath10ExpressionBPEL20)_oxpath;
        if(expr.isIsJoinExpression()){
            OLink olink = _oxpath.getLinks().get(localName);

            try {
                return _xpathEvalCtx.isLinkActive(olink) ? Boolean.TRUE : Boolean.FALSE;
            } catch (FaultException e) {
                throw new WrappedFaultException.JaxenUnresolvableException(e);
            }
        }else{
            String varName;
            String partName;
            int dotloc = localName.indexOf('.');
            if (dotloc == -1) {
                varName = localName;
                partName = null;
            } else {
                varName = localName.substring(0, dotloc);
                partName = localName.substring(dotloc + 1);
            }
            OScope.Variable variable = _oxpath.getVars().get(varName);
            OMessageVarType.Part part = partName == null ? null : ((OMessageVarType)variable.getType()).getParts().get(partName);

            try{
                Node variableNode = _xpathEvalCtx.readVariable(variable, part);
                if (variableNode == null)
                    throw new WrappedFaultException.JaxenUnresolvableException(
                            new FaultException(variable.getOwner().getConstants().getQnSelectionFailure(),
                                    "Unknown variable " + localName));
                OVarType type = variable.getType();
                if (type instanceof OMessageVarType) {
                    OMessageVarType.Part typePart = ((OMessageVarType)type).getParts().get(partName);
                    if (typePart == null) {
                        throw new WrappedFaultException.JaxenUnresolvableException(
                                new FaultException(variable.getOwner().getConstants().getQnSelectionFailure(),
                                        "Unknown part " + partName + " for variable " + localName));
                    }
                    type = typePart.getType();
                }

                if (_xpathEvalCtx.narrowTypes() && type instanceof OXsdTypeVarType && ((OXsdTypeVarType)type).isSimple()) {
                	String value = variableNode.getTextContent();
                	OXsdTypeVarType theType = (OXsdTypeVarType)type;

                        // cast booleans to boolean
                	if (BOOLEAN.equals(theType.getXsdType())) {
                        return new Boolean(value) ;
                    }

                    // and numbers to numbers (XPath only understands Double, so Double it shall be.
                    if (INT.equals(theType.getXsdType()) || UNSIGNED_SHORT.equals(theType.getXsdType()) ||
                            INTEGER.equals(theType.getXsdType()) ||
                            LONG.equals(theType.getXsdType()) || UNSIGNED_INT.equals(theType.getXsdType()) ||
                            SHORT.equals(theType.getXsdType()) || UNSIGNED_BYTE.equals(theType.getXsdType()) ||
                            BYTE.equals(theType.getXsdType()) ||
                            DECIMAL.equals(theType.getXsdType()) ||
                            FLOAT.equals(theType.getXsdType()) ||
                            DOUBLE.equals(theType.getXsdType())
                            ) {
                        return new Double(value);
                    }

                    return value;
                } else {
                    return variableNode;
                }
            }catch(FaultException e){
                __log.error("bpws:getVariableValue threw FaultException", e);
                throw new WrappedFaultException.JaxenUnresolvableException(e);
            }
        }
    }

    /**
     * bpws:getVariableData()
     */
    class BpelVariableDataFunction implements Function {
        public Object call(Context context, List args)
                throws FunctionCallException {
            if (__log.isDebugEnabled()) {
                __log.debug("call(context=" + context + " args=" + args + ")");
            }

            String varname  = (String) args.get(0);
            String partname = args.size() > 1 ? (String) args.get(1) : null;
            String xpathStr = args.size() > 2 ? (String)args.get(2) : null;

            OXPath10Expression.OSigGetVariableData sig = _oxpath.resolveGetVariableDataSig(varname,partname,xpathStr);
            if (sig == null) {
                String msg = "InternalError: Attempt to use an unknown getVariableData signature: " + args;
                if (__log.isFatalEnabled())
                    __log.fatal(msg);
                throw new FunctionCallException(msg);
            }

            try {
                Node ret = _xpathEvalCtx.readVariable(sig.getVariable(), sig.getPart());
                if (sig.getLocation() != null)
                    ret = _xpathEvalCtx.evaluateQuery(ret, sig.getLocation());

                if (__log.isDebugEnabled()) {
                    __log.debug("bpws:getVariableData(" + args +  ")' = " + ret);
                }

                return ret;
            } catch (FaultException e) {
                __log.error("bpws:getVariableData(" + args + ") threw FaultException", e);
                throw new WrappedFaultException.JaxenFunctionException(e);
            } catch (EvaluationException e) {
                __log.error("bpws:getVariableData(" + args + ") threw EvaluationException", e);
                if (e.getCause() instanceof FaultException) {
                    throw new WrappedFaultException.JaxenFunctionException((FaultException) e.getCause());
                } else {
                    throw new FunctionCallException("SubLanguageException: Unable to evaluate query expression", e);
                }
            }
        }
    }

    /**
     * bpws:getVariableProperty()
     */
    class BpelVariablePropertyFunction implements Function {
        public Object call(Context context, List args)
                throws FunctionCallException {
            if (args.size() != 2) {
                throw new FunctionCallException("missing required arguments");
            }

            OScope.Variable var = _oxpath.getVars().get(args.get(0));
            OProcess.OProperty property = _oxpath.getProperties().get(args.get(1));

            if (__log.isDebugEnabled()) {
                __log.debug("function call:'bpws:getVariableProperty(" + var + ","
                        + property + ")'");
            }

            try {
                return _xpathEvalCtx.readMessageProperty(var, property);
            } catch (FaultException e) {
                __log.error("bpws:getVariableProperty(" + args + ") threw FaultException", e);
                throw new WrappedFaultException.JaxenFunctionException(e);
            }
        }
    }

    class GetLinkStatusFunction implements Function {
        public Object call(Context context, List args)
                throws FunctionCallException {
            assert args.size() == 1;

            OLink olink = _oxpath.getLinks().get(args.get(0));

            try {
                return _xpathEvalCtx.isLinkActive(olink) ? Boolean.TRUE : Boolean.FALSE;
            } catch (FaultException e) {
                __log.error("bpws:getLinkStatus(" + args + ") threw FaultException", e);
                throw new WrappedFaultException.JaxenFunctionException(e);
            }
        }
    }

    class DoXslTransformFunction implements Function {
        public Object call(Context context, List args) throws FunctionCallException {
            assert args.size() >= 2;
            assert args.size() % 2 == 0;
            if (__log.isDebugEnabled()) {
                __log.debug("call(context=" + context + " args=" + args + ")");
            }
            if(!(_oxpath instanceof OXPath10ExpressionBPEL20)) {
                throw new IllegalStateException("XPath function bpws:doXslTransform not supported in " +
                        "BPEL 1.1!");
            }

            Element varElmt;
            try {
                if (args.get(1) instanceof List) {
                    List elmts = (List)args.get(1);
                    if (elmts.size() != 1) throw new WrappedFaultException.JaxenFunctionException(
                            new FaultException(_oxpath.getOwner().getConstants().getQnXsltInvalidSource(),
                                    "Second parameter of the bpws:doXslTransform function MUST point to a single " +
                                            "element node."));
                    varElmt = (Element) elmts.get(0);
                } else {
                    if (args.get(1) instanceof NodeWrapper)
                        varElmt = (Element) ((NodeWrapper)args.get(1)).getUnderlyingNode();
                    else varElmt = (Element) args.get(1);

//                    varElmt = (Element) args.get(1);
                }
            } catch (ClassCastException e) {
                throw new WrappedFaultException.JaxenFunctionException(
                        new FaultException(_oxpath.getOwner().getConstants().getQnXsltInvalidSource(),
                                "Second parameter of the bpws:doXslTransform function MUST point to a single " +
                                        "element node."));
            }

            URI xslUri;
            try {
                xslUri = new URI((String) args.get(0));
            } catch (URISyntaxException use) {
                // Shouldn't happen, checked at compilation time
                throw new FunctionCallException("First parameter of the bpws:doXslTransform isn't a valid URI!", use);
            }
            OXslSheet xslSheet = _oxpath.getXslSheet(xslUri);
            // Shouldn't happen, checked at compilation time
            if (xslSheet == null) throw new FunctionCallException("Couldn't find the XSL sheet " + args.get(0)
                    + ", process compilation or deployment was probably incomplete!");

            if (!(varElmt instanceof Element)) {
                throw new WrappedFaultException.JaxenFunctionException(
                        new FaultException(_oxpath.getOwner().getConstants().getQnXsltInvalidSource(),
                                "Second parameter of the bpws:doXslTransform function MUST point to a single " +
                                        "element node."));
            }

            HashMap<QName, Object> parametersMap = null;
            if (args.size() > 2) {
                parametersMap = new HashMap<QName, Object>();
                for (int idx = 2; idx < args.size(); idx+=2) {
                    QName keyQName = _oxpath.getNamespaceCtx().derefQName((String) args.get(idx));
                    parametersMap.put(keyQName, args.get(idx + 1));
                }
            }

            Document varDoc = DOMUtils.newDocument();
            varDoc.appendChild(varDoc.importNode(varElmt, true));

            DOMSource source = new DOMSource(varDoc);
            Object result;
            XslRuntimeUriResolver resolver = new XslRuntimeUriResolver(_oxpath, _xpathEvalCtx.getBaseResourceURI());
            XslTransformHandler.getInstance().cacheXSLSheet(_xpathEvalCtx.getProcessQName(), xslUri, xslSheet.getSheetBody(), resolver);
            try {
                result = XslTransformHandler.getInstance().transform(_xpathEvalCtx.getProcessQName(), xslUri, source, parametersMap, resolver);
            } catch (Exception e) {
                throw new WrappedFaultException.JaxenFunctionException(
                        new FaultException(_oxpath.getOwner().getConstants().getQnSubLanguageExecutionFault(),
                                e.toString()));
            }
            return result;
        }
    }

}
