/*
 * Copyright 2019 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#ifndef DEBUGLAYERMANAGER_H_
#define DEBUGLAYERMANAGER_H_

#include "include/core/SkColor.h"
#include "include/core/SkImage.h"
#include "include/core/SkRefCnt.h"
#include "include/core/SkSize.h"
#include "include/private/SkTHash.h"
#include "tools/debugger/DebugCanvas.h"

#include <memory>
#include <vector>

class SkCanvas;
class SkJSONWriter;
class SkPicture;
class SkSurface;
class UrlDataManager;
struct SkIRect;

// A class to assist in playing back and debugging an mskp file containing offscreen layer commands.

// Holds SkPictures necessary to draw layers in one or more DebugCanvases. During
// recording of the mskp file on Android, each layer had a RenderNode id, which is recorded with
// the layer's draw commands.
// Creates one surface (cpu only for now) for each layer, and renders
// pictures to it up to the requested command using a DebugCanvas.

// Animations are expected to, but may not always use a layer on more than frame.
// the layer may be drawn to more than once, and each different draw is saved for reconstructing the
// layer as it was on any frame. Draws may be partial, meaning their commands were clipped to not
// cover the entire layer.

// Clients may ask for a rendering of a given layer by its RenderNode id and frame, and
// this class will return a rendering of how it looked on that frame.
// returning an SkImage snapshot of the internally managed surface.

class DebugLayerManager {
public:
    DebugLayerManager() {}

    // Store an SkPicture under a given nodeId (and under the currently set frame number)
    // `dirty` is the recorded rect that was used to call androidFramework_setDeviceClipRestriction
    // when the layer was drawn.
    void storeSkPicture(int nodeId, int frame, sk_sp<SkPicture> picture, SkIRect dirty);

    // Set's the command playback head for a given picture/draw event.
    void setCommand(int nodeId, int frame, int command);

    void drawLayerEventTo(SkSurface*, const int nodeId, const int frame);

    // getLayerAsImage draws the given layer as it would have looked on frame and returns an image.
    // Though each picture can be played back in as many ways as there are commands, we will let
    // that be determined by the user who sets an independent playhead for each draw event, tracked
    // here, so it stays how they left it.
    // For example: Say we are drawing a layer at frame 10.
    // Frame 0:  Layer was completely redrawn. By default we draw it to its last command. We always
    //           save the result by (nodeId, frame)
    // Frame 5:  Layer was partially redrawn, and the user has inspected this draw event, leaving
    //           its command playhead at command 50/100. We have drew this at the time and save how
    //           the result looked (all of the commands at frame 0, then half of the commands in the
    //           partial draw at frame 5)
    // Frame 10: Another partial redraw, un-altered, drawn on top of the result from frame 5. We
    //           return this as the image of how the layer should look on frame 10
    // Frame 15: A full redraw
    //
    // If the user then comes along and moves the command playhead of the picture at frame 0,
    // we invalidate the stored images for 0, 5, and 10, but we can leave 15 alone if we have it.
    //
    // Which leaves us with one less degree of freedom to think about when implementing this
    // function: We can assume there is only one way to play back a given picture. :)
    //
    // The reason the public version of this function doesn't let you specify the frame, is that
    // I expect DebugCanvas to call it, which doesn't know which frame it's rendering. The code in
    // debugger_bindings.cpp does know, which it why I'm having it set the frame via setFrame(int)
    sk_sp<SkImage> getLayerAsImage(const int nodeId, const int frame);

    // Flat because it's meant to be bindable by emscripten and returned to the javascript side
    struct DrawEventSummary {
        // true when the drawEvent represents a valid result.
        bool found = false;
        int commandCount;
        int layerWidth;
        int layerHeight;
    };
    // return the summary of a single event
    DrawEventSummary event(int nodeId, int frame) const;

    struct LayerSummary {
        int nodeId;
        // Last frame less than or equal to the given frame which has an update for this layer
        // -1 if the layer has no updates satisfying that constraint.
        int frameOfLastUpdate;
        // Whether the last update was a full redraw.
        bool fullRedraw;
        int layerWidth;
        int layerHeight;
    };
    // Return a list summarizing all layers, with info relevant to the current frame.
    std::vector<LayerSummary> summarizeLayers(int frame) const;

    // Return the list of node ids which have DrawEvents on the given frame
    std::vector<int> listNodesForFrame(int frame) const;
    // Return the list of frames on which the given node had DrawEvents.
    std::vector<int> listFramesForNode(int nodeId) const;

    // asks the DebugCanvas of the indicated draw event to serialize it's commands as JSON.
    void toJSON(SkJSONWriter&, UrlDataManager&, SkCanvas*, int nodeId, int frame);

    // return a pointer to the debugcanvas of a given draw event.
    DebugCanvas* getEventDebugCanvas(int nodeid, int frame);

    // forwards the provided setting to all debugcanvases.
    void setOverdrawViz(bool overdrawViz);
    void setClipVizColor(SkColor clipVizColor);
    void setDrawGpuOpBounds(bool drawGpuOpBounds);

    struct LayerKey{
        int frame; // frame of animation on which this event was recorded.
        int nodeId; // the render node id of the layer which was drawn to.

        bool operator==(const LayerKey& b) const {
            return this->frame==b.frame && this->nodeId==b.nodeId;
        }
    };

    // return list of keys that identify layer update events
    const std::vector<DebugLayerManager::LayerKey>& getKeys() const { return keys; }

private:
    // This class is basically a map from (frame, node) to draw-event
    // during recording, at the beginning of any frame, one or more layers could have been drawn on.
    // every draw event was recorded, and when reading the mskp file they are stored and organized
    // here.

    struct DrawEvent {
        // true the pic's clip equals the layer bounds.
        bool fullRedraw;
        // the saved result of how the layer looks on this frame.
        // null if we don't have it.
        sk_sp<SkImage> image;
        // A debug canvas used for drawing this picture.
        // the SkPicture itself isn't saved, since it's in the DebugCanvas.
        std::unique_ptr<DebugCanvas> debugCanvas;
        // the command index where the debugCanvas was left off.
        int command;
        // the size of the layer this drew into. redundant between multiple DrawEvents on the same
        // layer but helpful.
        SkISize layerBounds;
    };

    SkTHashMap<LayerKey, DrawEvent> fDraws;
    // The list of all keys in the map above (it has no keys() method)
    std::vector<LayerKey> keys;
};

#endif
