/*
 * Copyright (C) 2013 Adobe Systems Inc. All rights reserved.
 * Copyright (C) 2009 Apple Inc. All rights reserved.
 * Copyright (C) 2011 Google Inc. All rights reserved.
 * Copyright (C) 2009 Joseph Pecoraro
 *
 * 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.
 * 3.  Neither the name of Apple Inc. ("Apple") nor the names of
 *     its contributors may be used to endorse or promote products derived
 *     from this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "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 APPLE OR ITS CONTRIBUTORS 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.
 */

#include "config.h"
#include "InspectorNodeFinder.h"

#include "Attr.h"
#include "Document.h"
#include "Element.h"
#include "HTMLFrameOwnerElement.h"
#include "NodeList.h"
#include "NodeTraversal.h"
#include "XPathNSResolver.h"
#include "XPathResult.h"

namespace WebCore {

static String stripCharacters(const String& string, const char startCharacter, const char endCharacter, bool& startCharFound, bool& endCharFound)
{
    startCharFound = string.startsWith(startCharacter);
    endCharFound = string.endsWith(endCharacter);

    unsigned start = startCharFound ? 1 : 0;
    unsigned end = string.length() - (endCharFound ? 1 : 0);
    return string.substring(start, end - start);
}

InspectorNodeFinder::InspectorNodeFinder(const String& query, bool caseSensitive)
    : m_query(query)
    , m_caseSensitive(caseSensitive)
{
    m_tagNameQuery = stripCharacters(query, '<', '>', m_startTagFound, m_endTagFound);

    bool startQuoteFound, endQuoteFound;
    m_attributeQuery = stripCharacters(query, '"', '"', startQuoteFound, endQuoteFound);
    m_exactAttributeMatch = startQuoteFound && endQuoteFound;
}

void InspectorNodeFinder::performSearch(Node* parentNode)
{
    if (!parentNode)
        return;

    searchUsingXPath(*parentNode);
    searchUsingCSSSelectors(*parentNode);

    // Keep the DOM tree traversal last. This way iframe content will come after their parents.
    searchUsingDOMTreeTraversal(*parentNode);
}

void InspectorNodeFinder::searchUsingDOMTreeTraversal(Node& parentNode)
{
    // Manual plain text search.
    for (auto* node = &parentNode; node; node = NodeTraversal::next(*node, &parentNode)) {
        switch (node->nodeType()) {
        case Node::TEXT_NODE:
        case Node::COMMENT_NODE:
        case Node::CDATA_SECTION_NODE:
            if (checkContains(node->nodeValue(), m_query))
                m_results.add(node);
            break;
        case Node::ELEMENT_NODE:
            if (matchesElement(downcast<Element>(*node)))
                m_results.add(node);
            if (is<HTMLFrameOwnerElement>(downcast<Element>(*node)))
                performSearch(downcast<HTMLFrameOwnerElement>(*node).contentDocument());
            break;
        default:
            break;
        }
    }
}

bool InspectorNodeFinder::checkEquals(const String& a, const String& b)
{
    if (m_caseSensitive)
        return a == b;
    return equalIgnoringASCIICase(a, b);
}

bool InspectorNodeFinder::checkContains(const String& a, const String& b)
{
    if (m_caseSensitive)
        return a.contains(b);
    return a.containsIgnoringASCIICase(b);
}

bool InspectorNodeFinder::checkStartsWith(const String& a, const String& b)
{
    if (m_caseSensitive)
        return a.startsWith(b);
    return a.startsWithIgnoringASCIICase(b);
}

bool InspectorNodeFinder::checkEndsWith(const String& a, const String& b)
{
    if (m_caseSensitive)
        return a.endsWith(b);
    return a.endsWithIgnoringASCIICase(b);
}

bool InspectorNodeFinder::matchesAttribute(const Attribute& attribute)
{
    if (checkContains(attribute.localName().string(), m_query))
        return true;

    auto value = attribute.value().string();
    return m_exactAttributeMatch ? checkEquals(value, m_attributeQuery) : checkContains(value, m_attributeQuery);
}

bool InspectorNodeFinder::matchesElement(const Element& element)
{
    String nodeName = element.nodeName();
    if ((!m_startTagFound && !m_endTagFound && checkContains(nodeName, m_tagNameQuery))
        || (m_startTagFound && m_endTagFound && checkEquals(nodeName, m_tagNameQuery))
        || (m_startTagFound && !m_endTagFound && checkStartsWith(nodeName, m_tagNameQuery))
        || (!m_startTagFound && m_endTagFound && checkEndsWith(nodeName, m_tagNameQuery)))
        return true;

    if (!element.hasAttributes())
        return false;

    for (const Attribute& attribute : element.attributesIterator()) {
        if (matchesAttribute(attribute))
            return true;
    }

    return false;
}

void InspectorNodeFinder::searchUsingXPath(Node& parentNode)
{
    auto evaluateResult = parentNode.document().evaluate(m_query, &parentNode, nullptr, XPathResult::ORDERED_NODE_SNAPSHOT_TYPE, nullptr);
    if (evaluateResult.hasException())
        return;
    auto result = evaluateResult.releaseReturnValue();

    auto snapshotLengthResult = result->snapshotLength();
    if (snapshotLengthResult.hasException())
        return;
    unsigned size = snapshotLengthResult.releaseReturnValue();

    for (unsigned i = 0; i < size; ++i) {
        auto snapshotItemResult = result->snapshotItem(i);
        if (snapshotItemResult.hasException())
            return;
        Node* node = snapshotItemResult.releaseReturnValue();

        if (is<Attr>(*node))
            node = downcast<Attr>(*node).ownerElement();

        // XPath can get out of the context node that we pass as the starting point to evaluate, so we need to filter for just the nodes we care about.
        if (parentNode.contains(node))
            m_results.add(node);
    }
}

void InspectorNodeFinder::searchUsingCSSSelectors(Node& parentNode)
{
    if (!is<ContainerNode>(parentNode))
        return;

    auto queryResult = downcast<ContainerNode>(parentNode).querySelectorAll(m_query);
    if (queryResult.hasException())
        return;

    auto nodeList = queryResult.releaseReturnValue();
    unsigned size = nodeList->length();
    for (unsigned i = 0; i < size; ++i)
        m_results.add(nodeList->item(i));
}

} // namespace WebCore
