/*
 * 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 = WTF::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
