/*
 * 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 "AnimatorManager.h"
#include "CanvasTransform.h"
#include "Debug.h"
#include "DisplayList.h"
#include "Matrix.h"
#include "RenderProperties.h"
#include "pipeline/skia/SkiaDisplayList.h"
#include "pipeline/skia/SkiaLayer.h"
#include "utils/FatVector.h"

#include <vector>

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,
    };

    ANDROID_API RenderNode();
    ANDROID_API virtual ~RenderNode();

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

    ANDROID_API void setStagingDisplayList(DisplayList* newData);

    ANDROID_API void output();
    ANDROID_API int getDebugSize();

    bool isRenderable() const { return mDisplayList && !mDisplayList->isEmpty(); }

    bool hasProjectionReceiver() const {
        return mDisplayList && mDisplayList->projectionReceiveIndex >= 0;
    }

    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);
            }
        }
    }

    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(); }

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

    // UI thread only!
    ANDROID_API 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 == nullptr || properties().getAlpha() <= 0 ||
               (outline.getShouldClip() && outline.isEmpty()) || properties().getScaleX() == 0 ||
               properties().getScaleY() == 0;
    }

    const DisplayList* getDisplayList() const { 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 ANDROID_API 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;
    };

    // Note this is not thread safe, this needs to be called
    // before the RenderNode is used for drawing.
    // RenderNode takes ownership of the pointer
    ANDROID_API void setPositionListener(PositionListener* listener) {
        mPositionListener = listener;
    }

    // This is only modified in MODE_FULL, so it can be safely accessed
    // on the UI thread.
    ANDROID_API 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;
    }

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

    void syncProperties();
    void syncDisplayList(TreeObserver& observer, 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);

    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;

    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;

    sp<PositionListener> mPositionListener;

    UsageHint mUsageHint = UsageHint::Unknown;

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

    /**
     * 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();
        }
    }

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

    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;

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