/*
 * Copyright (C) 2020 Apple Inc. All rights reserved.
 *
 * 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 APPLE INC. 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 INC. 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 "AppHighlightStorage.h"

#include "AppHighlight.h"
#include "AppHighlightRangeData.h"
#include "Chrome.h"
#include "ChromeClient.h"
#include "Document.h"
#include "DocumentMarkerController.h"
#include "Editor.h"
#include "ElementInlines.h"
#include "HTMLBodyElement.h"
#include "HighlightRegister.h"
#include "Node.h"
#include "Position.h"
#include "RenderedDocumentMarker.h"
#include "SimpleRange.h"
#include "StaticRange.h"
#include "TextIndicator.h"
#include "TextIterator.h"
#include <wtf/UUID.h>

namespace WebCore {

#if ENABLE(APP_HIGHLIGHTS)

static constexpr unsigned textPreviewLength = 500;

static RefPtr<Node> findNodeByPathIndex(const Node& parent, unsigned pathIndex, const String& nodeName)
{
    if (!is<ContainerNode>(parent))
        return nullptr;

    for (auto* child = downcast<ContainerNode>(parent).firstChild(); child; child = child->nextSibling()) {
        if (nodeName != child->nodeName())
            continue;

        if (!pathIndex--)
            return child;
    }
    return nullptr;
}

static std::pair<RefPtr<Node>, size_t> findNodeStartingAtPathComponentIndex(const AppHighlightRangeData::NodePath& path, Node& initialNode, size_t initialIndexToFollow)
{
    if (initialIndexToFollow >= path.size())
        return { nullptr, initialIndexToFollow };

    RefPtr currentNode = &initialNode;
    size_t currentPathIndex = initialIndexToFollow;
    for (; currentPathIndex < path.size(); ++currentPathIndex) {
        auto& component = path[currentPathIndex];
        auto nextNode = findNodeByPathIndex(*currentNode, component.pathIndex, component.nodeName);
        if (!nextNode)
            return { nullptr, currentPathIndex };

        if (is<CharacterData>(*nextNode) && downcast<CharacterData>(*nextNode).data() != component.textData)
            return { nullptr, currentPathIndex };

        currentNode = WTFMove(nextNode);
    }
    return { currentNode, currentPathIndex };
}

static RefPtr<Node> findNode(const AppHighlightRangeData::NodePath& path, Document& document)
{
    if (path.isEmpty() || !document.body())
        return nullptr;

    auto [foundNode, nextIndex] = findNodeStartingAtPathComponentIndex(path, *document.body(), 0);
    if (foundNode)
        return foundNode;

    while (nextIndex < path.size()) {
        auto& component = path[nextIndex++];
        if (component.identifier.isEmpty())
            continue;

        RefPtr elementWithIdentifier = document.getElementById(component.identifier);
        if (!elementWithIdentifier || elementWithIdentifier->nodeName() != component.nodeName)
            continue;

        std::tie(foundNode, nextIndex) = findNodeStartingAtPathComponentIndex(path, *elementWithIdentifier, nextIndex);
        if (foundNode)
            return foundNode;
    }

    return nullptr;
}

static std::optional<SimpleRange> findRangeByIdentifyingStartAndEndPositions(const AppHighlightRangeData& range, Document& document)
{
    auto startContainer = findNode(range.startContainer(), document);
    if (!startContainer)
        return std::nullopt;

    auto endContainer = findNode(range.endContainer(), document);
    if (!endContainer)
        return std::nullopt;

    auto start = makeContainerOffsetPosition(startContainer.get(), range.startOffset());
    auto end = makeContainerOffsetPosition(endContainer.get(), range.endOffset());
    if (start.isOrphan() || end.isOrphan())
        return std::nullopt;

    return makeSimpleRange(start, end);
}

static std::optional<SimpleRange> findRangeBySearchingText(const AppHighlightRangeData& range, Document& document)
{
    HashSet<String> identifiersInStartPath;
    for (auto& component : range.startContainer()) {
        if (!component.identifier.isEmpty())
            identifiersInStartPath.add(component.identifier);
    }

    RefPtr<Element> foundElement = document.body();
    for (auto iterator = range.endContainer().rbegin(), end = range.endContainer().rend(); iterator != end; ++iterator) {
        auto elementIdentifier = iterator->identifier;
        if (elementIdentifier.isEmpty() || !identifiersInStartPath.contains(elementIdentifier))
            continue;

        foundElement = document.getElementById(elementIdentifier);
        if (foundElement)
            break;
    }

    if (!foundElement)
        return std::nullopt;

    auto foundElementRange = makeRangeSelectingNodeContents(*foundElement);
    auto foundText = plainText(foundElementRange);
    if (auto index = foundText.find(range.text()); index != notFound && index == foundText.reverseFind(range.text()))
        return resolveCharacterRange(foundElementRange, { index, range.text().length() });

    return std::nullopt;
}

static std::optional<SimpleRange> findRange(const AppHighlightRangeData& range, Document& document)
{
    if (auto foundRange = findRangeByIdentifyingStartAndEndPositions(range, document))
        return foundRange;

    return findRangeBySearchingText(range, document);
}

static unsigned computePathIndex(const Node& node)
{
    String nodeName = node.nodeName();
    unsigned index = 0;
    for (auto* previousSibling = node.previousSibling(); previousSibling; previousSibling = previousSibling->previousSibling()) {
        if (previousSibling->nodeName() == nodeName)
            index++;
    }
    return index;
}

static AppHighlightRangeData::NodePathComponent createNodePathComponent(const Node& node)
{
    return {
        is<Element>(node) ? downcast<Element>(node).getIdAttribute().string() : nullString(),
        node.nodeName(),
        is<CharacterData>(node) ? downcast<CharacterData>(node).data() : nullString(),
        computePathIndex(node)
    };
}

static AppHighlightRangeData::NodePath makeNodePath(RefPtr<Node>&& node)
{
    AppHighlightRangeData::NodePath components;
    auto body = node->document().body();
    for (auto ancestor = node; ancestor && ancestor != body; ancestor = ancestor->parentNode())
        components.append(createNodePathComponent(*ancestor));
    components.reverse();
    return { components };
}

static AppHighlightRangeData createAppHighlightRangeData(const StaticRange& range)
{
    auto text = plainText(range);
    text.truncate(textPreviewLength);
    auto identifier = createCanonicalUUIDString();

    return {
        identifier,
        text,
        makeNodePath(&range.startContainer()),
        range.startOffset(),
        makeNodePath(&range.endContainer()),
        range.endOffset()
    };
}

AppHighlightStorage::AppHighlightStorage(Document& document)
    : m_document(document)
{
}

AppHighlightStorage::~AppHighlightStorage() = default;

void AppHighlightStorage::storeAppHighlight(Ref<StaticRange>&& range)
{
    auto data = createAppHighlightRangeData(range);
    std::optional<String> text;

    if (!data.text().isEmpty())
        text = data.text();

    AppHighlight highlight = {data.toSharedBuffer(), text, CreateNewGroupForHighlight::No, HighlightRequestOriginatedInApp::No};

    m_document->page()->chrome().storeAppHighlight(WTFMove(highlight));
}

void AppHighlightStorage::restoreAndScrollToAppHighlight(Ref<SharedBuffer>&& buffer, ScrollToHighlight scroll)
{
    auto appHighlightRangeData = AppHighlightRangeData::create(buffer);
    if (!appHighlightRangeData)
        return;
    
    if (!attemptToRestoreHighlightAndScroll(appHighlightRangeData.value(), scroll)) {
        if (scroll == ScrollToHighlight::Yes)
            m_unrestoredScrollHighlight = appHighlightRangeData;
        else
            m_unrestoredHighlights.append(appHighlightRangeData.value());
    }
    
    m_timeAtLastRangeSearch = MonotonicTime::now();
}

bool AppHighlightStorage::attemptToRestoreHighlightAndScroll(AppHighlightRangeData& highlight, ScrollToHighlight scroll)
{
    if (!m_document)
        return false;
    
    RefPtr strongDocument = m_document.get();
    
    auto range = findRange(highlight, *strongDocument);
    
    if (!range)
        return false;
    
    strongDocument->appHighlightRegister().addAppHighlight(StaticRange::create(*range));
    
    if (scroll == ScrollToHighlight::Yes) {
        auto textIndicator = TextIndicator::createWithRange(range.value(), { TextIndicatorOption::DoNotClipToVisibleRect }, WebCore::TextIndicatorPresentationTransition::Bounce);
        if (textIndicator)
            m_document->page()->chrome().client().setTextIndicator(textIndicator->data());

        TemporarySelectionChange selectionChange(*strongDocument, { range.value() }, { TemporarySelectionOption::DelegateMainFrameScroll, TemporarySelectionOption::SmoothScroll, TemporarySelectionOption::RevealSelectionBounds });
    }

    return true;
}

void AppHighlightStorage::restoreUnrestoredAppHighlights()
{
    Vector<AppHighlightRangeData> remainingRanges;
    
    for (auto& highlight : m_unrestoredHighlights) {
        if (!attemptToRestoreHighlightAndScroll(highlight, ScrollToHighlight::No))
            remainingRanges.append(highlight);
    }
    if (m_unrestoredScrollHighlight) {
        if (attemptToRestoreHighlightAndScroll(m_unrestoredScrollHighlight.value(), ScrollToHighlight::Yes))
            m_unrestoredScrollHighlight.reset();
    }
        
    m_timeAtLastRangeSearch = MonotonicTime::now();
    m_unrestoredHighlights = WTFMove(remainingRanges);
}

#endif

} // namespace WebCore
