/*
 * Copyright (C) 2014 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#pragma once

#include <SkMatrix.h>

#include <utils/LinearAllocator.h>
#include <utils/RefBase.h>
#include <utils/String8.h>

#include <cutils/compiler.h>

#include <androidfw/ResourceTypes.h>

#include <ui/FatVector.h>

#include "AnimatorManager.h"
#include "CanvasTransform.h"
#include "Debug.h"
#include "DisplayList.h"
#include "Matrix.h"
#include "RenderProperties.h"
#include "pipeline/skia/HolePunch.h"
#include "pipeline/skia/SkiaDisplayList.h"
#include "pipeline/skia/SkiaLayer.h"

#include <vector>
#include <pipeline/skia/StretchMask.h>

class SkBitmap;
class SkPaint;
class SkPath;
class SkRegion;
class SkSurface;

namespace android {
namespace uirenderer {

class CanvasState;
class Rect;
class SkiaShader;
struct RenderNodeOp;

class TreeInfo;
class TreeObserver;

namespace proto {
class RenderNode;
}

/**
 * Primary class for storing recorded canvas commands, as well as per-View/ViewGroup display
 * properties.
 *
 * Recording of canvas commands is somewhat similar to SkPicture, except the canvas-recording
 * functionality is split between RecordingCanvas (which manages the recording), DisplayList
 * (which holds the actual data), and RenderNode (which holds properties used for render playback).
 *
 * Note that DisplayList is swapped out from beneath an individual RenderNode when a view's
 * recorded stream of canvas operations is refreshed. The RenderNode (and its properties) stay
 * attached.
 */
class RenderNode : public VirtualLightRefBase {
    friend class TestUtils;  // allow TestUtils to access syncDisplayList / syncProperties

public:
    enum DirtyPropertyMask {
        GENERIC = 1 << 1,
        TRANSLATION_X = 1 << 2,
        TRANSLATION_Y = 1 << 3,
        TRANSLATION_Z = 1 << 4,
        SCALE_X = 1 << 5,
        SCALE_Y = 1 << 6,
        ROTATION = 1 << 7,
        ROTATION_X = 1 << 8,
        ROTATION_Y = 1 << 9,
        X = 1 << 10,
        Y = 1 << 11,
        Z = 1 << 12,
        ALPHA = 1 << 13,
        DISPLAY_LIST = 1 << 14,
    };

    RenderNode();
    virtual ~RenderNode();

    // See flags defined in DisplayList.java
    enum ReplayFlag { kReplayFlag_ClipChildren = 0x1 };

    void setStagingDisplayList(DisplayList&& newData);
    void discardStagingDisplayList();

    void output();
    int getUsageSize();
    int getAllocatedSize();

    bool isRenderable() const { return mDisplayList.hasContent(); }

    bool hasProjectionReceiver() const {
        return mDisplayList.containsProjectionReceiver();
    }

    const char* getName() const { return mName.string(); }

    void setName(const char* name) {
        if (name) {
            const char* lastPeriod = strrchr(name, '.');
            if (lastPeriod) {
                mName.setTo(lastPeriod + 1);
            } else {
                mName.setTo(name);
            }
        }
    }

    StretchMask& getStretchMask() { return mStretchMask; }

    VirtualLightRefBase* getUserContext() const { return mUserContext.get(); }

    void setUserContext(VirtualLightRefBase* context) { mUserContext = context; }

    bool isPropertyFieldDirty(DirtyPropertyMask field) const {
        return mDirtyPropertyFields & field;
    }

    void setPropertyFieldsDirty(uint32_t fields) { mDirtyPropertyFields |= fields; }

    const RenderProperties& properties() const { return mProperties; }

    RenderProperties& animatorProperties() { return mProperties; }

    const RenderProperties& stagingProperties() { return mStagingProperties; }

    RenderProperties& mutateStagingProperties() { return mStagingProperties; }

    bool isValid() { return mValid; }

    int getWidth() const { return properties().getWidth(); }

    int getHeight() const { return properties().getHeight(); }

    virtual void prepareTree(TreeInfo& info);
    void destroyHardwareResources(TreeInfo* info = nullptr);
    void destroyLayers();

    // UI thread only!
    void addAnimator(const sp<BaseRenderNodeAnimator>& animator);
    void removeAnimator(const sp<BaseRenderNodeAnimator>& animator);

    // This can only happen during pushStaging()
    void onAnimatorTargetChanged(BaseRenderNodeAnimator* animator) {
        mAnimatorManager.onAnimatorTargetChanged(animator);
    }

    AnimatorManager& animators() { return mAnimatorManager; }

    void applyViewPropertyTransforms(mat4& matrix, bool true3dTransform = false) const;

    bool nothingToDraw() const {
        const Outline& outline = properties().getOutline();
        return !mDisplayList.isValid() || properties().getAlpha() <= 0 ||
               (outline.getShouldClip() && outline.isEmpty()) || properties().getScaleX() == 0 ||
               properties().getScaleY() == 0;
    }

    const DisplayList& getDisplayList() const { return mDisplayList; }
    // TODO: can this be cleaned up?
    DisplayList& getDisplayList() { return mDisplayList; }

    // Note: The position callbacks are relying on the listener using
    // the frameNumber to appropriately batch/synchronize these transactions.
    // There is no other filtering/batching to ensure that only the "final"
    // state called once per frame.
    class PositionListener : public VirtualLightRefBase {
    public:
        virtual ~PositionListener() {}
        // Called when the RenderNode's position changes
        virtual void onPositionUpdated(RenderNode& node, const TreeInfo& info) = 0;
        // Called when the RenderNode no longer has a position. As in, it's
        // no longer being drawn.
        // Note, tree info might be null
        virtual void onPositionLost(RenderNode& node, const TreeInfo* info) = 0;
    };

    void setPositionListener(PositionListener* listener) {
        mStagingPositionListener = listener;
        mPositionListenerDirty = true;
    }

    // This is only modified in MODE_FULL, so it can be safely accessed
    // on the UI thread.
    bool hasParents() { return mParentCount; }

    void onRemovedFromTree(TreeInfo* info);

    // Called by CanvasContext to promote a RenderNode to be a root node
    void makeRoot() { incParentRefCount(); }

    // Called by CanvasContext when it drops a RenderNode from being a root node
    void clearRoot();

    void output(std::ostream& output, uint32_t level);

    void setUsageHint(UsageHint usageHint) { mUsageHint = usageHint; }

    UsageHint usageHint() const { return mUsageHint; }

    int64_t uniqueId() const { return mUniqueId; }

    void setIsTextureView() { mIsTextureView = true; }

    void markDrawStart(SkCanvas& canvas);
    void markDrawEnd(SkCanvas& canvas);

private:
    void computeOrderingImpl(RenderNodeOp* opState,
                             std::vector<RenderNodeOp*>* compositedChildrenOfProjectionSurface,
                             const mat4* transformFromProjectionSurface);

    void syncProperties();
    void syncDisplayList(TreeObserver& observer, TreeInfo* info);
    void handleForceDark(TreeInfo* info);

    void prepareTreeImpl(TreeObserver& observer, TreeInfo& info, bool functorsNeedLayer);
    void pushStagingPropertiesChanges(TreeInfo& info);
    void pushStagingDisplayListChanges(TreeObserver& observer, TreeInfo& info);
    void prepareLayer(TreeInfo& info, uint32_t dirtyMask);
    void pushLayerUpdate(TreeInfo& info);
    void deleteDisplayList(TreeObserver& observer, TreeInfo* info = nullptr);
    void damageSelf(TreeInfo& info);

    void incParentRefCount() { mParentCount++; }
    void decParentRefCount(TreeObserver& observer, TreeInfo* info = nullptr);

    const int64_t mUniqueId;
    String8 mName;
    sp<VirtualLightRefBase> mUserContext;

    uint32_t mDirtyPropertyFields;
    RenderProperties mProperties;
    RenderProperties mStagingProperties;

    // Owned by UI. Set when DL is set, cleared when DL cleared or when node detached
    // (likely by parent re-record/removal)
    bool mValid = false;

    bool mNeedsDisplayListSync;
    // WARNING: Do not delete this directly, you must go through deleteDisplayList()!
    DisplayList mDisplayList;
    DisplayList mStagingDisplayList;

    int64_t mDamageGenerationId;

    friend class AnimatorManager;
    AnimatorManager mAnimatorManager;

    /**
     * Draw time state - these properties are only set and used during rendering
     */

    // for projection surfaces, contains a list of all children items
    std::vector<RenderNodeOp*> mProjectedNodes;

    // How many references our parent(s) have to us. Typically this should alternate
    // between 2 and 1 (when a staging push happens we inc first then dec)
    // When this hits 0 we are no longer in the tree, so any hardware resources
    // (specifically Layers) should be released.
    // This is *NOT* thread-safe, and should therefore only be tracking
    // mDisplayList, not mStagingDisplayList.
    uint32_t mParentCount;

    bool mPositionListenerDirty = false;
    sp<PositionListener> mStagingPositionListener;
    sp<PositionListener> mPositionListener;

    UsageHint mUsageHint = UsageHint::Unknown;

    bool mHasHolePunches;
    StretchMask mStretchMask;

    bool mIsTextureView = false;

    // METHODS & FIELDS ONLY USED BY THE SKIA RENDERER
public:
    /**
     * Detach and transfer ownership of an already allocated displayList for use
     * in recording updated content for this renderNode
     */
    std::unique_ptr<skiapipeline::SkiaDisplayList> detachAvailableList() {
        return std::move(mAvailableDisplayList);
    }

    bool hasHolePunches() { return mHasHolePunches; }

    /**
     * Attach unused displayList to this node for potential future reuse.
     */
    void attachAvailableList(skiapipeline::SkiaDisplayList* skiaDisplayList) {
        mAvailableDisplayList.reset(skiaDisplayList);
    }

    /**
     * Returns true if an offscreen layer from any renderPipeline is attached
     * to this node.
     */
    bool hasLayer() const { return mSkiaLayer.get(); }

    /**
     * Used by the RenderPipeline to attach an offscreen surface to the RenderNode.
     * The surface is then will be used to store the contents of a layer.
     */
    void setLayerSurface(sk_sp<SkSurface> layer) {
        if (layer.get()) {
            if (!mSkiaLayer.get()) {
                mSkiaLayer = std::make_unique<skiapipeline::SkiaLayer>();
            }
            mSkiaLayer->layerSurface = std::move(layer);
            mSkiaLayer->inverseTransformInWindow.loadIdentity();
        } else {
            mSkiaLayer.reset();
        }

        mProperties.mutateLayerProperties().mutableStretchEffect().clear();
        mStretchMask.clear();
        // Clear out the previous snapshot and the image filter the previous
        // snapshot was created with whenever the layer changes.
        mSnapshotResult.snapshot = nullptr;
        mTargetImageFilter = nullptr;
    }

    /**
     * If the RenderNode is of type LayerType::RenderLayer then this method will
     * return the an offscreen rendering surface that is used to both render into
     * the layer and composite the layer into its parent.  If the type is not
     * LayerType::RenderLayer then it will return a nullptr.
     *
     * NOTE: this function is only guaranteed to return accurate results after
     *       prepareTree has been run for this RenderNode
     */
    SkSurface* getLayerSurface() const {
        return mSkiaLayer.get() ? mSkiaLayer->layerSurface.get() : nullptr;
    }

    struct SnapshotResult {
        sk_sp<SkImage> snapshot;
        SkIRect outSubset;
        SkIPoint outOffset;
    };

    std::optional<SnapshotResult> updateSnapshotIfRequired(GrRecordingContext* context,
                                            const SkImageFilter* imageFilter,
                                            const SkIRect& clipBounds);

    skiapipeline::SkiaLayer* getSkiaLayer() const { return mSkiaLayer.get(); }

    /**
     * Returns the path that represents the outline of RenderNode intersected with
     * the provided rect.  This call will internally cache the resulting path in
     * order to potentially return that path for subsequent calls to this method.
     * By reusing the same path we get better performance on the GPU backends since
     * those resources are cached in the hardware based on the path's genID.
     *
     * The returned path is only guaranteed to be valid until this function is called
     * again or the RenderNode's outline is mutated.
     */
    const SkPath* getClippedOutline(const SkRect& clipRect) const;

private:
    /**
     * If this RenderNode has been used in a previous frame then the SkiaDisplayList
     * from that frame is cached here until one of the following conditions is met:
     *  1) The RenderNode is deleted (causing this to be deleted)
     *  2) It is replaced with the displayList from the next completed frame
     *  3) It is detached and used to to record a new displayList for a later frame
     */
    std::unique_ptr<skiapipeline::SkiaDisplayList> mAvailableDisplayList;

    /**
     * An offscreen rendering target used to contain the contents this RenderNode
     * when it has been set to draw as a LayerType::RenderLayer.
     */
    std::unique_ptr<skiapipeline::SkiaLayer> mSkiaLayer;

    /**
     * SkImageFilter used to create the mSnapshotResult
     */
    sk_sp<SkImageFilter> mTargetImageFilter;
    uint32_t mTargetImageFilterLayerSurfaceGenerationId = 0;

    /**
     * Clip bounds used to create the mSnapshotResult
     */
    SkIRect mImageFilterClipBounds;

    /**
     * Result of the most recent snapshot with additional metadata used to
     * determine how to draw the contents
     */
    SnapshotResult mSnapshotResult;

    struct ClippedOutlineCache {
        // keys
        uint32_t outlineID = 0;
        SkRect clipRect;

        // value
        SkPath clippedOutline;
    };
    mutable ClippedOutlineCache mClippedOutlineCache;
};  // class RenderNode

class MarkAndSweepRemoved : public TreeObserver {
    PREVENT_COPY_AND_ASSIGN(MarkAndSweepRemoved);

public:
    explicit MarkAndSweepRemoved(TreeInfo* info) : mTreeInfo(info) {}

    void onMaybeRemovedFromTree(RenderNode* node) override { mMarked.emplace_back(node); }

    ~MarkAndSweepRemoved() {
        for (auto& node : mMarked) {
            if (!node->hasParents()) {
                node->onRemovedFromTree(mTreeInfo);
            }
        }
    }

private:
    FatVector<sp<RenderNode>, 10> mMarked;
    TreeInfo* mTreeInfo;
};

} /* namespace uirenderer */
} /* namespace android */
