/*
 * 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 "src/core/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
