/*
 * Copyright (C) 2019 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.
 */

#pragma once

#include "Position.h"
#include "QualifiedName.h"
#include <wtf/CompletionHandler.h>
#include <wtf/EnumTraits.h>
#include <wtf/ObjectIdentifier.h>
#include <wtf/WeakHashSet.h>
#include <wtf/WeakPtr.h>

namespace WebCore {

class Document;
class Element;
class VisiblePosition;

class TextManipulationController : public CanMakeWeakPtr<TextManipulationController> {
    WTF_MAKE_FAST_ALLOCATED;
public:
    TextManipulationController(Document&);

    enum TokenIdentifierType { };
    using TokenIdentifier = ObjectIdentifier<TokenIdentifierType>;

    struct ManipulationTokenInfo {
        String tagName;
        String roleAttribute;
        URL documentURL;
        bool isVisible { false };

        template<class Encoder> void encode(Encoder&) const;
        template<class Decoder> static std::optional<ManipulationTokenInfo> decode(Decoder&);
    };

    struct ManipulationToken {
        TokenIdentifier identifier;
        String content;
        std::optional<ManipulationTokenInfo> info;
        bool isExcluded { false };

        template<class Encoder> void encode(Encoder&) const;
        template<class Decoder> static std::optional<ManipulationToken> decode(Decoder&);
    };

    enum ItemIdentifierType { };
    using ItemIdentifier = ObjectIdentifier<ItemIdentifierType>;

    struct ManipulationItem {
        ItemIdentifier identifier;
        Vector<ManipulationToken> tokens;

        template<class Encoder> void encode(Encoder&) const;
        template<class Decoder> static std::optional<ManipulationItem> decode(Decoder&);
    };

    struct ExclusionRule {
        enum class Type : uint8_t { Exclude, Include };

        struct ElementRule {
            AtomString localName;

            template<class Encoder> void encode(Encoder&) const;
            template<class Decoder> static std::optional<ElementRule> decode(Decoder&);
        };

        struct AttributeRule {
            AtomString name;
            String value;

            template<class Encoder> void encode(Encoder&) const;
            template<class Decoder> static std::optional<AttributeRule> decode(Decoder&);
        };

        struct ClassRule {
            AtomString className;

            template<class Encoder> void encode(Encoder&) const;
            template<class Decoder> static std::optional<ClassRule> decode(Decoder&);
        };

        Type type;
        std::variant<ElementRule, AttributeRule, ClassRule> rule;

        bool match(const Element&) const;

        template<class Encoder> void encode(Encoder&) const;
        template<class Decoder> static std::optional<ExclusionRule> decode(Decoder&);
    };

    using ManipulationItemCallback = Function<void(Document&, const Vector<ManipulationItem>&)>;
    WEBCORE_EXPORT void startObservingParagraphs(ManipulationItemCallback&&, Vector<ExclusionRule>&& = { });

    void didCreateRendererForElement(Element&);
    void didCreateRendererForTextNode(Text&);
    void didUpdateContentForText(Text&);
    void removeNode(Node&);

    enum class ManipulationFailureType : uint8_t {
        ContentChanged,
        InvalidItem,
        InvalidToken,
        ExclusionViolation,
    };

    struct ManipulationFailure {
        ItemIdentifier identifier;
        uint64_t index;
        ManipulationFailureType type;

        template<class Encoder> void encode(Encoder&) const;
        template<class Decoder> static std::optional<ManipulationFailure> decode(Decoder&);
    };

    WEBCORE_EXPORT Vector<ManipulationFailure> completeManipulation(const Vector<ManipulationItem>&);

private:
    void observeParagraphs(const Position& start, const Position& end);
    void scheduleObservationUpdate();

    struct ManipulationItemData {
        Position start;
        Position end;

        WeakPtr<Element> element;
        QualifiedName attributeName { nullQName() };

        Vector<ManipulationToken> tokens;
    };

    struct ManipulationUnit {
        Ref<Node> node;
        Vector<ManipulationToken> tokens;
        bool areAllTokensExcluded { true };
        bool firstTokenContainsDelimiter { false };
        bool lastTokenContainsDelimiter { false };
    };
    ManipulationUnit createUnit(const Vector<String>&, Node&);
    void parse(ManipulationUnit&, const String&, Node&);

    bool shouldExcludeNodeBasedOnStyle(const Node&);

    void addItem(ManipulationItemData&&);
    void addItemIfPossible(Vector<ManipulationUnit>&&);
    void flushPendingItemsForCallback();

    enum class IsNodeManipulated : bool { No, Yes };
    struct NodeInsertion {
        RefPtr<Node> parentIfDifferentFromCommonAncestor;
        Ref<Node> child;
        IsNodeManipulated isChildManipulated { IsNodeManipulated::Yes };
    };
    using NodeEntry = std::pair<Ref<Node>, Ref<Node>>;
    Vector<Ref<Node>> getPath(Node*, Node*);
    void updateInsertions(Vector<NodeEntry>&, const Vector<Ref<Node>>&, Node*, HashSet<Ref<Node>>&, Vector<NodeInsertion>&);
    std::optional<ManipulationFailureType> replace(const ManipulationItemData&, const Vector<ManipulationToken>&, HashSet<Ref<Node>>& containersWithoutVisualOverflowBeforeReplacement);

    WeakPtr<Document> m_document;
    WeakHashSet<Element> m_elementsWithNewRenderer;
    WeakHashSet<Text> m_manipulatedTextsWithNewContent;
    WeakHashSet<Node> m_textNodesWithNewRenderer;
    WeakHashSet<Node> m_manipulatedNodes;

    HashMap<String, bool> m_cachedFontFamilyExclusionResults;

    bool m_didScheduleObservationUpdate { false };

    ManipulationItemCallback m_callback;
    Vector<ManipulationItem> m_pendingItemsForCallback;

    Vector<ExclusionRule> m_exclusionRules;
    HashMap<ItemIdentifier, ManipulationItemData> m_items;
    ItemIdentifier m_itemIdentifier;
    TokenIdentifier m_tokenIdentifier;
};

template<class Encoder>
void TextManipulationController::ManipulationTokenInfo::encode(Encoder& encoder) const
{
    encoder << tagName;
    encoder << roleAttribute;
    encoder << documentURL;
    encoder << isVisible;
}

template<class Decoder>
std::optional<TextManipulationController::ManipulationTokenInfo> TextManipulationController::ManipulationTokenInfo::decode(Decoder& decoder)
{
    ManipulationTokenInfo result;
    if (!decoder.decode(result.tagName))
        return std::nullopt;

    if (!decoder.decode(result.roleAttribute))
        return std::nullopt;

    if (!decoder.decode(result.documentURL))
        return std::nullopt;

    if (!decoder.decode(result.isVisible))
        return std::nullopt;

    return result;
}

template<class Encoder>
void TextManipulationController::ManipulationToken::encode(Encoder& encoder) const
{
    encoder << identifier << content << info << isExcluded;
}

template<class Decoder>
std::optional<TextManipulationController::ManipulationToken> TextManipulationController::ManipulationToken::decode(Decoder& decoder)
{
    ManipulationToken result;
    if (!decoder.decode(result.identifier))
        return std::nullopt;
    if (!decoder.decode(result.content))
        return std::nullopt;
    if (!decoder.decode(result.info))
        return std::nullopt;
    if (!decoder.decode(result.isExcluded))
        return std::nullopt;
    return result;
}

template<class Encoder>
void TextManipulationController::ManipulationItem::encode(Encoder& encoder) const
{
    encoder << identifier << tokens;
}

template<class Decoder>
std::optional<TextManipulationController::ManipulationItem> TextManipulationController::ManipulationItem::decode(Decoder& decoder)
{
    ManipulationItem result;
    if (!decoder.decode(result.identifier))
        return std::nullopt;
    if (!decoder.decode(result.tokens))
        return std::nullopt;
    return result;
}

template<class Encoder>
void TextManipulationController::ExclusionRule::encode(Encoder& encoder) const
{
    encoder << type << rule;
}

template<class Decoder>
std::optional<TextManipulationController::ExclusionRule> TextManipulationController::ExclusionRule::decode(Decoder& decoder)
{
    ExclusionRule result;
    if (!decoder.decode(result.type))
        return std::nullopt;
    if (!decoder.decode(result.rule))
        return std::nullopt;
    return result;
}

template<class Encoder>
void TextManipulationController::ExclusionRule::ElementRule::encode(Encoder& encoder) const
{
    encoder << localName;
}

template<class Decoder>
std::optional<TextManipulationController::ExclusionRule::ElementRule> TextManipulationController::ExclusionRule::ElementRule::decode(Decoder& decoder)
{
    ElementRule result;
    if (!decoder.decode(result.localName))
        return std::nullopt;
    return result;
}

template<class Encoder>
void TextManipulationController::ExclusionRule::AttributeRule::encode(Encoder& encoder) const
{
    encoder << name << value;
}

template<class Decoder>
std::optional<TextManipulationController::ExclusionRule::AttributeRule> TextManipulationController::ExclusionRule::AttributeRule::decode(Decoder& decoder)
{
    AttributeRule result;
    if (!decoder.decode(result.name))
        return std::nullopt;
    if (!decoder.decode(result.value))
        return std::nullopt;
    return result;
}

template<class Encoder>
void TextManipulationController::ExclusionRule::ClassRule::encode(Encoder& encoder) const
{
    encoder << className;
}

template<class Decoder>
std::optional<TextManipulationController::ExclusionRule::ClassRule> TextManipulationController::ExclusionRule::ClassRule::decode(Decoder& decoder)
{
    ClassRule result;
    if (!decoder.decode(result.className))
        return std::nullopt;
    return result;
}

template<class Encoder>
void TextManipulationController::ManipulationFailure::encode(Encoder& encoder) const
{
    encoder << identifier << index << type;
}

template<class Decoder>
std::optional<TextManipulationController::ManipulationFailure> TextManipulationController::ManipulationFailure::decode(Decoder& decoder)
{
    ManipulationFailure result;
    if (!decoder.decode(result.identifier))
        return std::nullopt;
    if (!decoder.decode(result.index))
        return std::nullopt;
    if (!decoder.decode(result.type))
        return std::nullopt;
    return result;
}

} // namespace WebCore

namespace WTF {

template<> struct EnumTraits<WebCore::TextManipulationController::ExclusionRule::Type> {
    using ExclusionRule = WebCore::TextManipulationController::ExclusionRule;
    using values = EnumValues<
        ExclusionRule::Type,
        ExclusionRule::Type::Include,
        ExclusionRule::Type::Exclude
    >;
};

template<> struct EnumTraits<WebCore::TextManipulationController::ManipulationFailureType> {
    using ManipulationFailureType = WebCore::TextManipulationController::ManipulationFailureType;
    using values = EnumValues<
        ManipulationFailureType,
        ManipulationFailureType::ContentChanged,
        ManipulationFailureType::InvalidItem,
        ManipulationFailureType::InvalidToken,
        ManipulationFailureType::ExclusionViolation
    >;
};

} // namespace WTF
