/*
 * 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/SkiaDisplayList.h"
#include "pipeline/skia/SkiaLayer.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 getUsageSize();
    ANDROID_API int getAllocatedSize();

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

    bool hasProjectionReceiver() const {
        return mDisplayList && 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);
            }
        }
    }

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

    ANDROID_API 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.
    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; }

    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;

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