/*
 * 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 <SkCamera.h>
#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 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;

    // 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;

    /**
     * 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 */
