/*   Copyright 2004 The Apache Software Foundation
 *
 *   Licensed 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.xmlbeans.impl.store;

import java.io.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.*;

import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.lang.ref.WeakReference;
import java.math.BigDecimal;
import java.util.concurrent.locks.ReentrantReadWriteLock;

import org.apache.xmlbeans.impl.common.DefaultClassLoaderResourceLoader;
import org.apache.xmlbeans.impl.common.XPath;
import org.apache.xmlbeans.impl.common.XPath.XPathCompileException;
import org.apache.xmlbeans.impl.common.XPath.ExecutionContext;

import org.apache.xmlbeans.*;
import org.w3c.dom.Node;


// TODO - This class handled query *and* path ... rename it?

public abstract class Path
{
    public static final String PATH_DELEGATE_INTERFACE = "PATH_DELEGATE_INTERFACE";
    public static String _useDelegateForXpath = "use delegate for xpath";
    public static String _useXdkForXpath = "use xdk for xpath";
    public static String _useXqrlForXpath = "use xqrl for xpath";
    public static String _useXbeanForXpath = "use xbean for xpath";
    public static String _forceXqrl2002ForXpathXQuery = "use xqrl-2002 for xpath";

    private static final int USE_XBEAN    = 0x01;
    private static final int USE_XQRL     = 0x02;
    private static final int USE_DELEGATE = 0x04;
    private static final int USE_XQRL2002 = 0x08;
    private static final int USE_XDK      = 0x10;

    private static Map _xbeanPathCache = new WeakHashMap();
    private static Map _xdkPathCache = new WeakHashMap();
    private static Map _xqrlPathCache = new WeakHashMap();
    private static Map _xqrl2002PathCache = new WeakHashMap();

    private static Method _xdkCompilePath;
    private static Method _xqrlCompilePath;
    private static Method _xqrl2002CompilePath;

    private static boolean _xdkAvailable = true;
    private static boolean _xqrlAvailable = true;
    private static boolean _xqrl2002Available = true;

    private static final String _delIntfName;
    private static final ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    static
    {
        String id = "META-INF/services/org.apache.xmlbeans.impl.store.PathDelegate.SelectPathInterface";
        InputStream in = new DefaultClassLoaderResourceLoader().getResourceAsStream(id);

        String name = null;
        if(in != null) {
            try {
                BufferedReader br = new BufferedReader(new InputStreamReader(in));
                name = br.readLine().trim();
                br.close();
            } catch (Exception e) {
                // set nothing
            }
        }

        _delIntfName = name;
    }

    protected final String _pathKey;

    Path(String key)
    {
        _pathKey = key;
    }


    interface PathEngine
    {
        void release();

        boolean next(Cur c);
    }

    abstract PathEngine execute(Cur c, XmlOptions options);

    //
    //
    //

    static String getCurrentNodeVar(XmlOptions options)
    {
        String currentNodeVar = "this";

        options = XmlOptions.maskNull(options);

        if (options.hasOption(XmlOptions.XQUERY_CURRENT_NODE_VAR)) {
            currentNodeVar = (String) options.get(XmlOptions.XQUERY_CURRENT_NODE_VAR);

            if (currentNodeVar.startsWith("$")) {
                throw new IllegalArgumentException("Omit the '$' prefix for the current node variable");
            }
        }

        return currentNodeVar;
    }

    public static Path getCompiledPath(String pathExpr, XmlOptions options)
    {
        options = XmlOptions.maskNull(options);

        int force =
                options.hasOption(_useDelegateForXpath) ? USE_DELEGATE
                : options.hasOption(_useXqrlForXpath) ? USE_XQRL
                : options.hasOption(_useXdkForXpath) ? USE_XDK
                : options.hasOption(_useXbeanForXpath) ? USE_XBEAN
                : options.hasOption(_forceXqrl2002ForXpathXQuery) ? USE_XQRL2002
                : USE_XBEAN|USE_XQRL|USE_XDK|USE_DELEGATE; //set all bits except XQRL2002
        String delIntfName = 
            options.hasOption(PATH_DELEGATE_INTERFACE) ? 
                (String)options.get(PATH_DELEGATE_INTERFACE) : _delIntfName;

        return getCompiledPath(pathExpr, force, getCurrentNodeVar(options), delIntfName);
    }

    static Path getCompiledPath(String pathExpr, int force,
        String currentVar, String delIntfName)
    {
        Path path = null;
        WeakReference pathWeakRef = null;
        Map namespaces = (force & USE_DELEGATE) != 0 ? new HashMap() : null;
        lock.readLock().lock();
        try {
        if ((force & USE_XBEAN) != 0)
            pathWeakRef = (WeakReference)_xbeanPathCache.get(pathExpr);
        if (pathWeakRef == null && (force & USE_XQRL) != 0)
            pathWeakRef = (WeakReference)_xqrlPathCache.get(pathExpr);
        if (pathWeakRef == null && (force & USE_XDK) != 0)
            pathWeakRef = (WeakReference)_xdkPathCache.get(pathExpr);
        if (pathWeakRef == null && (force & USE_XQRL2002) != 0)
            pathWeakRef = (WeakReference)_xqrl2002PathCache.get(pathExpr);

        if (pathWeakRef!=null)
            path = (Path)pathWeakRef.get();
        if (path != null)
            return path;
        } finally {
            lock.readLock().unlock();
        }
        lock.writeLock().lock();
        try {
        if ((force & USE_XBEAN) != 0) {
            pathWeakRef = (WeakReference)_xbeanPathCache.get(pathExpr);
            if (pathWeakRef != null)
                path = (Path)pathWeakRef.get();
            if (path==null)
            path = getCompiledPathXbean(pathExpr, currentVar, namespaces);
        }
        if (path == null && (force & USE_XQRL) != 0) {
            pathWeakRef = (WeakReference)_xqrlPathCache.get(pathExpr);
            if (pathWeakRef != null)
                path = (Path)pathWeakRef.get();
            if (path==null)
            path = getCompiledPathXqrl(pathExpr, currentVar);
        }
        if (path == null && (force & USE_XDK) != 0) {
            pathWeakRef = (WeakReference)_xdkPathCache.get(pathExpr);
            if (pathWeakRef != null)
                path = (Path)pathWeakRef.get();
            if (path==null)
            path = getCompiledPathXdk(pathExpr, currentVar);
        }
        if (path == null && (force & USE_DELEGATE) != 0) {
            path = getCompiledPathDelegate(pathExpr, currentVar, namespaces, delIntfName);
        }
        if (path == null && (force & USE_XQRL2002) != 0) {
            pathWeakRef = (WeakReference)_xqrl2002PathCache.get(pathExpr);
            if (pathWeakRef != null)
                path = (Path)pathWeakRef.get();
            if (path==null)
            path = getCompiledPathXqrl2002(pathExpr, currentVar);
        }
        if (path == null)
        {
            StringBuffer errMessage = new StringBuffer();
            if ((force & USE_XBEAN) != 0)
                errMessage.append(" Trying XBeans path engine...");
            if ((force & USE_XQRL) != 0)
                errMessage.append(" Trying XQRL...");
            if ((force & USE_XDK) != 0)
                errMessage.append(" Trying XDK...");
            if ((force & USE_DELEGATE) != 0)
                errMessage.append(" Trying delegated path engine...");
            if ((force & USE_XQRL2002) != 0)
                errMessage.append(" Trying XQRL2002...");

            throw new RuntimeException(errMessage.toString() + " FAILED on " + pathExpr);
        }
        } finally {
            lock.writeLock().unlock();
        }
        return path;
    }

    static private Path getCompiledPathXdk(String pathExpr, String currentVar)
    {
        Path path = createXdkCompiledPath(pathExpr, currentVar);
        if (path != null)
            _xdkPathCache.put(path._pathKey, new WeakReference(path));

        return path;
    }

    static private Path getCompiledPathXqrl(String pathExpr, String currentVar)
    {
        Path path = createXqrlCompiledPath(pathExpr, currentVar);
        if (path != null)
            _xqrlPathCache.put(path._pathKey, new WeakReference(path));

        return path;
    }

    static private Path getCompiledPathXqrl2002(String pathExpr, String currentVar)
    {
        Path path = createXqrl2002CompiledPath(pathExpr, currentVar);
        if (path != null)
            _xqrl2002PathCache.put(path._pathKey, new WeakReference(path));

        return path;
    }

    static private Path getCompiledPathXbean(String pathExpr,
        String currentVar, Map namespaces)
    {
        Path path = XbeanPath.create(pathExpr, currentVar, namespaces);
        if (path != null)
            _xbeanPathCache.put(path._pathKey, new WeakReference(path));

        return path;
    }

    static private Path getCompiledPathDelegate(String pathExpr, String currentVar, Map namespaces, String delIntfName)
    {
        Path path = null;
        if ( namespaces == null )
            namespaces = new HashMap();

        try
        {
            XPath.compileXPath(pathExpr, currentVar, namespaces);
        }
        catch (XPath.XPathCompileException e)
        {
            //do nothing, this function is only called to populate the namespaces map
        }

        int offset =
            namespaces.get(XPath._NS_BOUNDARY) == null ?
            0 :
            ((Integer) namespaces.get(XPath._NS_BOUNDARY)).intValue();
        namespaces.remove(XPath._NS_BOUNDARY);
        path = DelegatePathImpl.create(delIntfName,
            pathExpr.substring(offset),
            currentVar,
            namespaces);

        return path;
    }


    public static String compilePath(String pathExpr, XmlOptions options)
    {
        return getCompiledPath(pathExpr, options)._pathKey;
    }

    //
    // Xbean store specific implementation of compiled path
    //

    private static final class XbeanPath extends Path
    {
        static Path create(String pathExpr, String currentVar, Map namespaces)
        {
            try
            {
                return new XbeanPath(pathExpr, currentVar,
                                XPath.compileXPath(pathExpr, currentVar, namespaces));
            }
            catch (XPathCompileException e) {
                return null;
            }
        }

        private XbeanPath(String pathExpr, String currentVar, XPath xpath)
        {
            super(pathExpr);

            _currentVar = currentVar;
            _compiledPath = xpath;
        }

        PathEngine execute(Cur c, XmlOptions options)
        {
            options = XmlOptions.maskNull(options);
            String delIntfName = 
                options.hasOption(PATH_DELEGATE_INTERFACE) ? 
                    (String)options.get(PATH_DELEGATE_INTERFACE) : _delIntfName;

            // The builtin XPath engine works only on containers.  Delegate to
            // xqrl otherwise.  Also, if the path had a //. at the end, the
            // simple xpath engine can't do the generate case, it only handles
            // attrs and elements.

            if (!c.isContainer() || _compiledPath.sawDeepDot())
            {
                int force = USE_DELEGATE | USE_XQRL | USE_XDK;
                return getCompiledPath(_pathKey, force, _currentVar, delIntfName).execute(c, options);
            }
            return new XbeanPathEngine(_compiledPath, c);
        }

        private final String _currentVar;
        private final XPath _compiledPath;
        public Map namespaces;
    }

    private static Path createXdkCompiledPath(String pathExpr, String currentVar)
    {
        if (!_xdkAvailable)
            return null;

        if (_xdkCompilePath == null)
        {
            try
            {
                Class xdkImpl = Class.forName("org.apache.xmlbeans.impl.store.OXQXBXqrlImpl");

                _xdkCompilePath =
                    xdkImpl.getDeclaredMethod("compilePath",
                        new Class[]{String.class, String.class, Boolean.class});
            }
            catch (ClassNotFoundException e)
            {
                _xdkAvailable = false;
                return null;
            }
            catch (Exception e)
            {
                _xdkAvailable = false;
                throw new RuntimeException(e.getMessage(), e);
            }
        }

        Object[] args = new Object[]{pathExpr, currentVar, new Boolean(true)};

        try {
            return (Path) _xdkCompilePath.invoke(null, args);
        }
        catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            throw new RuntimeException(t.getMessage(), t);
        }
        catch (IllegalAccessException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    private static Path createXqrlCompiledPath(String pathExpr, String currentVar)
    {
        if (!_xqrlAvailable)
            return null;

        if (_xqrlCompilePath == null)
        {
            try
            {
                Class xqrlImpl = Class.forName("org.apache.xmlbeans.impl.store.XqrlImpl");

                _xqrlCompilePath =
                        xqrlImpl.getDeclaredMethod("compilePath",
                                new Class[]{String.class, String.class, Boolean.class});
            }
            catch (ClassNotFoundException e)
            {
                _xqrlAvailable = false;
                return null;
            }
            catch (Exception e)
            {
                _xqrlAvailable = false;
                throw new RuntimeException(e.getMessage(), e);
            }
        }

        Object[] args = new Object[]{pathExpr, currentVar, new Boolean(true)};

        try {
            return (Path) _xqrlCompilePath.invoke(null, args);
        }
        catch (InvocationTargetException e) {
            Throwable t = e.getCause();
            throw new RuntimeException(t.getMessage(), t);
        }
        catch (IllegalAccessException e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    private static Path createXqrl2002CompiledPath(String pathExpr, String currentVar)
    {
        if (!_xqrl2002Available)
            return null;

        if (_xqrl2002CompilePath == null)
        {
            try
            {
                Class xqrlImpl = Class.forName("org.apache.xmlbeans.impl.store.Xqrl2002Impl");

                _xqrl2002CompilePath =
                    xqrlImpl.getDeclaredMethod("compilePath",
                        new Class[]{String.class, String.class, Boolean.class});
            }
            catch (ClassNotFoundException e)
            {
                _xqrl2002Available = false;
                return null;
            }
            catch (Exception e)
            {
                _xqrl2002Available = false;
                throw new RuntimeException(e.getMessage(), e);
            }
        }

        Object[] args = new Object[]{pathExpr, currentVar, new Boolean(true)};

        try
        {
            return (Path) _xqrl2002CompilePath.invoke(null, args);
        }
        catch (InvocationTargetException e)
        {
            Throwable t = e.getCause();
            throw new RuntimeException(t.getMessage(), t);
        }
        catch (IllegalAccessException e)
        {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    private static final class XbeanPathEngine
        extends ExecutionContext
        implements PathEngine
    {
        XbeanPathEngine(XPath xpath, Cur c)
        {
            assert c.isContainer();

            _version = c._locale.version();
            _cur = c.weakCur(this);

            _cur.push();

            init(xpath);

            int ret = start();

            if ((ret & HIT) != 0)
                c.addToSelection();

            doAttrs(ret, c);

            if ((ret & DESCEND) == 0 || !Locale.toFirstChildElement(_cur))
                release();
        }

        private void advance(Cur c)
        {
            assert _cur != null;

            if (_cur.isFinish())
            {
                if (_cur.isAtEndOfLastPush())
                    release();
                else {
                    end();
                    _cur.next();
                }
            }
            else if (_cur.isElem())
            {
                int ret = element(_cur.getName());

                if ((ret & HIT) != 0)
                    c.addToSelection(_cur);

                doAttrs(ret, c);

                if ((ret & DESCEND) == 0 || !Locale.toFirstChildElement(_cur))
                {
                    end();
                    _cur.skip();
                }
            }
            else
            {
                do
                {
                    _cur.next();
                }
                while(!_cur.isContainerOrFinish());
            }
        }

        private void doAttrs(int ret, Cur c)
        {
            assert _cur.isContainer();

            if ((ret & ATTRS) != 0) {
                if (_cur.toFirstAttr()) {
                    do {
                        if (attr(_cur.getName()))
                            c.addToSelection(_cur);
                    }
                    while (_cur.toNextAttr());

                    _cur.toParent();
                }
            }
        }

        public boolean next(Cur c)
        {
            if (_cur != null && _version != _cur._locale.version())
                throw new ConcurrentModificationException("Document changed during select");

            int startCount = c.selectionCount();

            while (_cur != null) {
                advance(c);

                if (startCount != c.selectionCount())
                    return true;
            }

            return false;
        }

        public void release()
        {
            if (_cur != null) {
                _cur.release();
                _cur = null;
            }
        }

        private final long _version;
        private Cur _cur;
    }

    private static final class DelegatePathImpl
        extends Path
    {
        private PathDelegate.SelectPathInterface _xpathImpl;

        static Path create(String implClassName, String pathExpr, String currentNodeVar, Map namespaceMap)
        {
            assert !currentNodeVar.startsWith("$"); // cezar review with ericvas

            PathDelegate.SelectPathInterface impl =
                    PathDelegate.createInstance(implClassName, pathExpr, currentNodeVar, namespaceMap);
            if (impl == null)
                return null;

            return new DelegatePathImpl(impl, pathExpr);
        }


        private DelegatePathImpl(PathDelegate.SelectPathInterface xpathImpl,
                              String pathExpr)
        {
            super(pathExpr);
            _xpathImpl = xpathImpl;
        }

        protected PathEngine execute(Cur c, XmlOptions options)
        {
            return new DelegatePathEngine(_xpathImpl, c);
        }

        private static class DelegatePathEngine
                extends XPath.ExecutionContext
                implements PathEngine
        {
            // full datetime format: yyyy-MM-dd'T'HH:mm:ss'Z'
            private final DateFormat xmlDateFormat = new SimpleDateFormat("yyyy-MM-dd");

            DelegatePathEngine(PathDelegate.SelectPathInterface xpathImpl,
                               Cur c)
            {
                _engine = xpathImpl;
                _version = c._locale.version();
                _cur = c.weakCur(this);
            }

            public boolean next(Cur c)
            {
                if (!_firstCall)
                    return false;

                _firstCall = false;

                if (_cur != null && _version != _cur._locale.version())
                    throw new ConcurrentModificationException("Document changed during select");

                List resultsList;
                Object context_node;

                context_node = _cur.getDom();
                resultsList = _engine.selectPath(context_node);

                int i;
                for (i = 0; i < resultsList.size(); i++) {
                    //simple type function results
                    Object node = resultsList.get(i);
                    Cur pos = null;
                    if (!(node instanceof Node)) {
                        Object obj = resultsList.get(i);
                        String value;
                        if (obj instanceof Date) {
                            value = xmlDateFormat.format((Date) obj);
                        } else if (obj instanceof BigDecimal) {
                            value = ((BigDecimal)obj).toPlainString();
                        } else {
                            value = obj.toString();
                        }

                        //we cannot leave the cursor's locale, as
                        //everything is done in the selections of this cursor

                        Locale l = c._locale;
                        try {
                            pos = l.load("<xml-fragment/>").tempCur();
                            pos.setValue(value);     
                            SchemaType type = getType(node);
                            Locale.autoTypeDocument(pos, type, null);
                            //move the cur to the actual text
                            pos.next();
                        }
                        catch (Exception e) {
                            throw new RuntimeException(e);
                        }
                    }
                    else {
                        assert (node instanceof DomImpl.Dom):
                                "New object created in XPATH!";
                        pos = ((DomImpl.Dom) node).tempCur();

                    }
                    c.addToSelection(pos);
                    pos.release();
                }
                release();
                _engine = null;
                return true;
            }

            private SchemaType getType(Object node)
            {
                SchemaType type;
                if (node instanceof Integer)
                    type = XmlInteger.type;
                else if (node instanceof Double)
                    type = XmlDouble.type;
                else if (node instanceof Long)
                    type = XmlLong.type;
                else if (node instanceof Float)
                    type = XmlFloat.type;
                else if (node instanceof BigDecimal)
                    type = XmlDecimal.type;
                else if (node instanceof Boolean)
                    type = XmlBoolean.type;
                else if (node instanceof String)
                    type = XmlString.type;
                else if (node instanceof Date)
                    type = XmlDate.type;
                else
                    type = XmlAnySimpleType.type;
                return type;
            }

            public void release()
            {
                if (_cur != null) {
                    _cur.release();
                    _cur = null;
                }
            }

            private Cur _cur;
            private PathDelegate.SelectPathInterface _engine;
            private boolean _firstCall = true;
            private long _version;
        }
    }
}
