/*
 * Copyright (C) 2005 Frerich Raabe <raabe@kde.org>
 * Copyright (C) 2006, 2009 Apple Inc.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

#pragma once

#include <wtf/Vector.h>
#include <wtf/text/AtomicString.h>

namespace WebCore {

class Node;

namespace XPath {

class Expression;
class NodeSet;

class Step {
    WTF_MAKE_FAST_ALLOCATED;
public:
    enum Axis {
        AncestorAxis, AncestorOrSelfAxis, AttributeAxis,
        ChildAxis, DescendantAxis, DescendantOrSelfAxis,
        FollowingAxis, FollowingSiblingAxis, NamespaceAxis,
        ParentAxis, PrecedingAxis, PrecedingSiblingAxis,
        SelfAxis
    };

    class NodeTest {
        WTF_MAKE_FAST_ALLOCATED;
    public:
        enum Kind { TextNodeTest, CommentNodeTest, ProcessingInstructionNodeTest, AnyNodeTest, NameTest };

        explicit NodeTest(Kind kind) : m_kind(kind) { }
        NodeTest(Kind kind, const AtomicString& data) : m_kind(kind), m_data(data) { }
        NodeTest(Kind kind, const AtomicString& data, const AtomicString& namespaceURI) : m_kind(kind), m_data(data), m_namespaceURI(namespaceURI) { }

#if COMPILER(MSVC)
        NodeTest(const NodeTest&);
        void operator=(const NodeTest&);

        NodeTest(NodeTest&& other)
            : m_kind(other.m_kind)
            , m_data(WTFMove(other.m_data))
            , m_namespaceURI(WTFMove(other.m_namespaceURI))
            , m_mergedPredicates(WTFMove(other.m_mergedPredicates))
        {
        }
        NodeTest& operator=(NodeTest&& other)
        {
            m_kind = other.m_kind;
            m_data = WTFMove(other.m_data);
            m_namespaceURI = WTFMove(other.m_namespaceURI);
            m_mergedPredicates = WTFMove(other.m_mergedPredicates);
            return *this;
        }
#endif

    private:
        friend class Step;
        friend void optimizeStepPair(Step&, Step&, bool&);
        friend bool nodeMatchesBasicTest(Node&, Axis, const NodeTest&);
        friend bool nodeMatches(Node&, Axis, const NodeTest&);

        Kind m_kind;
        AtomicString m_data;
        AtomicString m_namespaceURI;
        Vector<std::unique_ptr<Expression>> m_mergedPredicates;
    };

    Step(Axis, NodeTest);
    Step(Axis, NodeTest, Vector<std::unique_ptr<Expression>>);
    ~Step();

    void optimize();

    void evaluate(Node& context, NodeSet&) const;

    Axis axis() const { return m_axis; }

private:
    friend void optimizeStepPair(Step&, Step&, bool&);

    bool predicatesAreContextListInsensitive() const;

    void parseNodeTest(const String&);
    void nodesInAxis(Node& context, NodeSet&) const;

    Axis m_axis;
    NodeTest m_nodeTest;
    Vector<std::unique_ptr<Expression>> m_predicates;
};

void optimizeStepPair(Step&, Step&, bool& dropSecondStep);

} // namespace XPath
} // namespace WebCore
