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

#if ENABLE(ASYNC_SCROLLING)

#include "GraphicsLayer.h"
#include "ScrollingCoordinator.h"
#include <stdint.h>
#include <wtf/ThreadSafeRefCounted.h>
#include <wtf/TypeCasts.h>
#include <wtf/Vector.h>

namespace WTF {
class TextStream;
}

namespace WebCore {

class GraphicsLayer;
class ScrollingStateTree;

// Used to allow ScrollingStateNodes to refer to layers in various contexts:
// a) Async scrolling, main thread: ScrollingStateNode holds onto a GraphicsLayer, and uses m_layerID
//    to detect whether that GraphicsLayer's underlying PlatformLayer changed.
// b) Threaded scrolling, commit to scrolling thread: ScrollingStateNode wraps a PlatformLayer, which
//    can be passed to the Scrolling Thread
// c) Remote scrolling UI process, where LayerRepresentation wraps just a PlatformLayerID.
class LayerRepresentation {
public:
    enum Type {
        EmptyRepresentation,
        GraphicsLayerRepresentation,
        PlatformLayerRepresentation,
        PlatformLayerIDRepresentation
    };

    LayerRepresentation() = default;

    LayerRepresentation(GraphicsLayer* graphicsLayer)
        : m_graphicsLayer(graphicsLayer)
        , m_layerID(graphicsLayer ? graphicsLayer->primaryLayerID() : 0)
        , m_representation(GraphicsLayerRepresentation)
    { }

    LayerRepresentation(PlatformLayer* platformLayer)
        : m_typelessPlatformLayer(makePlatformLayerTypeless(platformLayer))
        , m_representation(PlatformLayerRepresentation)
    {
        retainPlatformLayer(m_typelessPlatformLayer);
    }

    LayerRepresentation(GraphicsLayer::PlatformLayerID layerID)
        : m_layerID(layerID)
        , m_representation(PlatformLayerIDRepresentation)
    {
    }

    LayerRepresentation(const LayerRepresentation& other)
        : m_typelessPlatformLayer(other.m_typelessPlatformLayer)
        , m_layerID(other.m_layerID)
        , m_representation(other.m_representation)
    {
        if (m_representation == PlatformLayerRepresentation)
            retainPlatformLayer(m_typelessPlatformLayer);
    }

    ~LayerRepresentation()
    {
        if (m_representation == PlatformLayerRepresentation)
            releasePlatformLayer(m_typelessPlatformLayer);
    }

    explicit operator GraphicsLayer*() const
    {
        ASSERT(m_representation == GraphicsLayerRepresentation);
        return m_graphicsLayer.get();
    }

    explicit operator PlatformLayer*() const
    {
        ASSERT(m_representation == PlatformLayerRepresentation);
        return makePlatformLayerTyped(m_typelessPlatformLayer);
    }
    
    GraphicsLayer::PlatformLayerID layerID() const
    {
        return m_layerID;
    }

    explicit operator GraphicsLayer::PlatformLayerID() const
    {
        ASSERT(m_representation != PlatformLayerRepresentation);
        return m_layerID;
    }

    LayerRepresentation& operator=(const LayerRepresentation& other)
    {
        m_graphicsLayer = other.m_graphicsLayer;
        m_typelessPlatformLayer = other.m_typelessPlatformLayer;
        m_layerID = other.m_layerID;
        m_representation = other.m_representation;

        if (m_representation == PlatformLayerRepresentation)
            retainPlatformLayer(m_typelessPlatformLayer);

        return *this;
    }

    explicit operator bool() const
    {
        switch (m_representation) {
        case EmptyRepresentation:
            return false;
        case GraphicsLayerRepresentation:
            return !!m_graphicsLayer;
        case PlatformLayerRepresentation:
            return !!m_typelessPlatformLayer;
        case PlatformLayerIDRepresentation:
            return !!m_layerID;
        }
        ASSERT_NOT_REACHED();
        return false;
    }

    bool operator==(const LayerRepresentation& other) const
    {
        if (m_representation != other.m_representation)
            return false;
        switch (m_representation) {
        case EmptyRepresentation:
            return true;
        case GraphicsLayerRepresentation:
            return m_graphicsLayer == other.m_graphicsLayer
                && m_layerID == other.m_layerID;
        case PlatformLayerRepresentation:
            return m_typelessPlatformLayer == other.m_typelessPlatformLayer;
        case PlatformLayerIDRepresentation:
            return m_layerID == other.m_layerID;
        }
        ASSERT_NOT_REACHED();
        return true;
    }
    
    LayerRepresentation toRepresentation(Type representation) const
    {
        switch (representation) {
        case EmptyRepresentation:
            return LayerRepresentation();
        case GraphicsLayerRepresentation:
            ASSERT(m_representation == GraphicsLayerRepresentation);
            return LayerRepresentation(m_graphicsLayer.get());
        case PlatformLayerRepresentation:
            return m_graphicsLayer ? m_graphicsLayer->platformLayer() : nullptr;
        case PlatformLayerIDRepresentation:
            return LayerRepresentation(m_layerID);
        }
        ASSERT_NOT_REACHED();
        return LayerRepresentation();
    }

    bool representsGraphicsLayer() const { return m_representation == GraphicsLayerRepresentation; }
    bool representsPlatformLayerID() const { return m_representation == PlatformLayerIDRepresentation; }
    
private:
    WEBCORE_EXPORT static void retainPlatformLayer(void* typelessPlatformLayer);
    WEBCORE_EXPORT static void releasePlatformLayer(void* typelessPlatformLayer);
    WEBCORE_EXPORT static PlatformLayer* makePlatformLayerTyped(void* typelessPlatformLayer);
    WEBCORE_EXPORT static void* makePlatformLayerTypeless(PlatformLayer*);

    RefPtr<GraphicsLayer> m_graphicsLayer;
    void* m_typelessPlatformLayer { nullptr };
    GraphicsLayer::PlatformLayerID m_layerID { 0 };
    Type m_representation { EmptyRepresentation };
};

class ScrollingStateNode : public ThreadSafeRefCounted<ScrollingStateNode> {
    WTF_MAKE_FAST_ALLOCATED;
public:
    virtual ~ScrollingStateNode();
    
    ScrollingNodeType nodeType() const { return m_nodeType; }

    bool isFixedNode() const { return m_nodeType == ScrollingNodeType::Fixed; }
    bool isStickyNode() const { return m_nodeType == ScrollingNodeType::Sticky; }
    bool isPositionedNode() const { return m_nodeType == ScrollingNodeType::Positioned; }
    bool isScrollingNode() const { return isFrameScrollingNode() || isOverflowScrollingNode(); }
    bool isFrameScrollingNode() const { return m_nodeType == ScrollingNodeType::MainFrame || m_nodeType == ScrollingNodeType::Subframe; }
    bool isFrameHostingNode() const { return m_nodeType == ScrollingNodeType::FrameHosting; }
    bool isOverflowScrollingNode() const { return m_nodeType == ScrollingNodeType::Overflow; }
    bool isOverflowScrollProxyNode() const { return m_nodeType == ScrollingNodeType::OverflowProxy; }

    virtual Ref<ScrollingStateNode> clone(ScrollingStateTree& adoptiveTree) = 0;
    Ref<ScrollingStateNode> cloneAndReset(ScrollingStateTree& adoptiveTree);
    void cloneAndResetChildren(ScrollingStateNode&, ScrollingStateTree& adoptiveTree);

    // FIXME: using an OptionSet<> for these and derived class bits would simplify code.
    enum {
        Layer = 0,
        ChildNodes,
        NumStateNodeBits // This must remain at the last position.
    };
    typedef uint64_t ChangedProperties;

    bool hasChangedProperties() const { return m_changedProperties; }
    bool hasChangedProperty(unsigned propertyBit) const { return m_changedProperties & (static_cast<ChangedProperties>(1) << propertyBit); }
    void resetChangedProperties() { m_changedProperties = 0; }
    void setPropertyChanged(unsigned propertyBit);
    virtual void setPropertyChangedBitsAfterReattach();

    ChangedProperties changedProperties() const { return m_changedProperties; }
    void setChangedProperties(ChangedProperties changedProperties) { m_changedProperties = changedProperties; }
    
    virtual void reconcileLayerPositionForViewportRect(const LayoutRect& /*viewportRect*/, ScrollingLayerPositionAction) { }

    const LayerRepresentation& layer() const { return m_layer; }
    WEBCORE_EXPORT void setLayer(const LayerRepresentation&);

    ScrollingStateTree& scrollingStateTree() const { return m_scrollingStateTree; }

    ScrollingNodeID scrollingNodeID() const { return m_nodeID; }

    ScrollingStateNode* parent() const { return m_parent; }
    void setParent(ScrollingStateNode* parent) { m_parent = parent; }
    ScrollingNodeID parentNodeID() const { return m_parent ? m_parent->scrollingNodeID() : 0; }

    Vector<RefPtr<ScrollingStateNode>>* children() const { return m_children.get(); }
    std::unique_ptr<Vector<RefPtr<ScrollingStateNode>>> takeChildren() { return WTFMove(m_children); }

    void appendChild(Ref<ScrollingStateNode>&&);
    void insertChild(Ref<ScrollingStateNode>&&, size_t index);

    // Note that node ownership is via the parent, so these functions can trigger node deletion.
    void removeFromParent();
    void removeChildAtIndex(size_t index);
    void removeChild(ScrollingStateNode&);

    size_t indexOfChild(ScrollingStateNode&) const;

    String scrollingStateTreeAsText(ScrollingStateTreeAsTextBehavior = ScrollingStateTreeAsTextBehaviorNormal) const;

protected:
    ScrollingStateNode(const ScrollingStateNode&, ScrollingStateTree&);
    ScrollingStateNode(ScrollingNodeType, ScrollingStateTree&, ScrollingNodeID);

    virtual void dumpProperties(WTF::TextStream&, ScrollingStateTreeAsTextBehavior) const;

    inline void setPropertyChangedBit(unsigned propertyBit);

private:
    void dump(WTF::TextStream&, ScrollingStateTreeAsTextBehavior) const;

    const ScrollingNodeType m_nodeType;
    const ScrollingNodeID m_nodeID;
    ChangedProperties m_changedProperties { 0 };

    ScrollingStateTree& m_scrollingStateTree;

    ScrollingStateNode* m_parent { nullptr };
    std::unique_ptr<Vector<RefPtr<ScrollingStateNode>>> m_children;

    LayerRepresentation m_layer;
};

void ScrollingStateNode::setPropertyChangedBit(unsigned propertyBit)
{
    m_changedProperties |= (static_cast<ChangedProperties>(1) << propertyBit);
}

} // namespace WebCore

#define SPECIALIZE_TYPE_TRAITS_SCROLLING_STATE_NODE(ToValueTypeName, predicate) \
SPECIALIZE_TYPE_TRAITS_BEGIN(WebCore::ToValueTypeName) \
    static bool isType(const WebCore::ScrollingStateNode& node) { return node.predicate; } \
SPECIALIZE_TYPE_TRAITS_END()

#endif // ENABLE(ASYNC_SCROLLING)
