/*
 * This file defines SkpDebugPlayer, a class which loads a SKP or MSKP file and draws it
 * to an SkSurface with annotation, and detailed playback controls. It holds as many DebugCanvases
 * as there are frames in the file.
 *
 * It also defines emscripten bindings for SkpDebugPlayer and other classes necessary to us it.
 *
 * Copyright 2019 Google LLC
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "include/codec/SkCodec.h"
#include "include/core/SkFontMgr.h"
#include "include/core/SkImage.h"
#include "include/core/SkPicture.h"
#include "include/core/SkStream.h"
#include "include/core/SkString.h"
#include "include/core/SkSurface.h"
#include "include/docs/SkMultiPictureDocument.h"
#include "include/encode/SkPngEncoder.h"
#include "include/ports/SkFontMgr_empty.h"
#include "src/base/SkBase64.h"
#include "src/core/SkPicturePriv.h"
#include "src/ports/SkTypeface_FreeType.h"
#include "src/utils/SkJSONWriter.h"
#include "tools/SkSharingProc.h"
#include "tools/UrlDataManager.h"
#include "tools/debugger/DebugCanvas.h"
#include "tools/debugger/DebugLayerManager.h"
#include "tools/debugger/DrawCommand.h"

#include <memory>
#include <string>
#include <string_view>
#include <vector>
#include <map>
#include <emscripten.h>
#include <emscripten/bind.h>

#ifdef CK_ENABLE_WEBGL
#include "include/gpu/ganesh/GrBackendSurface.h"
#include "include/gpu/ganesh/GrDirectContext.h"
#include "include/gpu/ganesh/SkSurfaceGanesh.h"
#include "include/gpu/ganesh/gl/GrGLInterface.h"
#include "include/gpu/ganesh/gl/GrGLTypes.h"

#include <GL/gl.h>
#include <emscripten/html5.h>
#endif

#include "modules/canvaskit/WasmCommon.h"

// file signature for SkMultiPictureDocument
// TODO(nifong): make public and include from SkMultiPictureDocument.h
static constexpr char kMultiMagic[] = "Skia Multi-Picture Doc\n\n";

uint32_t MinVersion() { return SkPicturePriv::kMin_Version; }

struct ImageInfoNoColorspace {
    int width;
    int height;
    SkColorType colorType;
    SkAlphaType alphaType;
};

// TODO(kjlubick) Should this handle colorspace
ImageInfoNoColorspace toImageInfoNoColorspace(const SkImageInfo& ii) {
  return (ImageInfoNoColorspace){ii.width(), ii.height(), ii.colorType(), ii.alphaType()};
}

static sk_sp<SkImage> deserializeImage(sk_sp<SkData> data, std::optional<SkAlphaType> at, void*) {
  std::unique_ptr<SkCodec> codec = DecodeImageData(std::move(data));
  if (!codec) {
    SkDebugf("Could not decode an image\n");
    return nullptr;
  }
  // Force the decode to happen instead of returning a lazy image.
  return SkCodecs::DeferredImage(std::move(codec), at)->makeRasterImage(nullptr);
}

static sk_sp<SkTypeface> deserializeTypeface(SkStream& stream, void* ctx) {
    return SkTypeface::MakeDeserialize(&stream, *static_cast<sk_sp<SkFontMgr>*>(ctx));
}

static void register_typeface() {
  static SkOnce once;
  once([] {
    SkTypeface::Register(SkTypeface_FreeType::FactoryId,
                         SkTypeface_FreeType::MakeFromStream );
  });
}

class SkpDebugPlayer {
  public:
    SkpDebugPlayer() :
    udm(UrlDataManager(SkString("/data"))){}

    /* loadSkp deserializes a skp file that has been copied into the shared WASM memory.
     * cptr - a pointer to the data to deserialize.
     * length - length of the data in bytes.
     * The caller must allocate the memory with M._malloc where M is the wasm module in javascript
     * and copy the data into M.buffer at the pointer returned by malloc.
     *
     * uintptr_t is used here because emscripten will not allow binding of functions with pointers
     * to primitive types. We can instead pass a number and cast it to whatever kind of
     * pointer we're expecting.
     *
     * Returns an error string which is populated in the case that the file cannot be read.
     */
    std::string loadSkp(uintptr_t cptr, int length) {
      const uint8_t* data = reinterpret_cast<const uint8_t*>(cptr);
      // Both traditional and multi-frame skp files have a magic word
      SkMemoryStream stream(data, length);
      SkDebugf("make stream at %p, with %d bytes\n",data, length);
      const bool isMulti = memcmp(data, kMultiMagic, sizeof(kMultiMagic) - 1) == 0;


      if (isMulti) {
        SkDebugf("Try reading as a multi-frame skp\n");
        const auto& error = loadMultiFrame(&stream);
        if (!error.empty()) { return error; }
      } else {
        SkDebugf("Try reading as single-frame skp\n");
        // TODO(nifong): Rely on SkPicture's return errors once it provides some.
        std::unique_ptr<DebugCanvas> canvas = loadSingleFrame(&stream);
        if (!canvas) {
          return "Error loading single frame";
        }
        frames.push_back(std::move(canvas));
      }
      return "";
    }

    /* drawTo asks the debug canvas to draw from the beginning of the picture
     * to the given command and flush the canvas.
     */
    void drawTo(SkSurface* surface, int32_t index) {
      // Set the command within the frame or layer event being drawn.
      if (fInspectedLayer >= 0) {
        fLayerManager->setCommand(fInspectedLayer, fp, index);
      } else {
        index = constrainFrameCommand(index);
      }

      auto* canvas = surface->getCanvas();
      canvas->clear(SK_ColorTRANSPARENT);
      if (fInspectedLayer >= 0) {
        // when it's a layer event we're viewing, we use the layer manager to render it.
        fLayerManager->drawLayerEventTo(surface, fInspectedLayer, fp);
      } else {
        // otherwise, its a frame at the top level.
        frames[fp]->drawTo(surface->getCanvas(), index);
      }
#ifdef CK_ENABLE_WEBGL
      skgpu::ganesh::Flush(surface);
#endif
    }

    // Draws to the end of the current frame.
    void draw(SkSurface* surface) {
      auto* canvas = surface->getCanvas();
      canvas->clear(SK_ColorTRANSPARENT);
      frames[fp]->draw(surface->getCanvas());
#ifdef CK_ENABLE_WEBGL
      skgpu::ganesh::Flush(surface);
#endif
    }

    // Gets the bounds for the given frame
    // (or layer update, assuming there is one at that frame for fInspectedLayer)
    SkIRect getBoundsForFrame(int32_t frame) {
        if (fInspectedLayer < 0) {
            return fBoundsArray[frame];
        }
        auto summary = fLayerManager->event(fInspectedLayer, fp);
        return SkIRect::MakeWH(summary.layerWidth, summary.layerHeight);
    }

    // Gets the bounds for the current frame
    const SkIRect getBounds() {
      return getBoundsForFrame(fp);
    }

    // returns the debugcanvas of the current frame, or the current draw event when inspecting
    // a layer.
    DebugCanvas* visibleCanvas() {
      if (fInspectedLayer >=0) {
        return fLayerManager->getEventDebugCanvas(fInspectedLayer, fp);
      } else {
        return frames[fp].get();
      }
    }

    // The following three operations apply to every debugcanvas because they are overdraw features.
    // There is only one toggle for them on the app, they are global settings.
    // However, there's not a simple way to make the debugcanvases pull settings from a central
    // location so we set it on all of them at once.
    void setOverdrawVis(bool on) {
      for (size_t i=0; i < frames.size(); i++) {
        frames[i]->setOverdrawViz(on);
      }
      fLayerManager->setOverdrawViz(on);
    }
    void setGpuOpBounds(bool on) {
      for (size_t i=0; i < frames.size(); i++) {
        frames[i]->setDrawGpuOpBounds(on);
      }
      fLayerManager->setDrawGpuOpBounds(on);
    }
    void setClipVizColor(JSColor color) {
      for (size_t i=0; i < frames.size(); i++) {
        frames[i]->setClipVizColor(SkColor(color));
      }
      fLayerManager->setClipVizColor(SkColor(color));
    }
    void setAndroidClipViz(bool on) {
      for (size_t i=0; i < frames.size(); i++) {
        frames[i]->setAndroidClipViz(on);
      }
      // doesn't matter in layers
    }
    void setOriginVisible(bool on) {
      for (size_t i=0; i < frames.size(); i++) {
        frames[i]->setOriginVisible(on);
      }
    }
    // The two operations below only apply to the current frame, because they concern the command
    // list, which is unique to each frame.
    void deleteCommand(int index) {
      visibleCanvas()->deleteDrawCommandAt(index);
    }
    void setCommandVisibility(int index, bool visible) {
      visibleCanvas()->toggleCommand(index, visible);
    }
    int getSize() const {
      if (fInspectedLayer >=0) {
        return fLayerManager->event(fInspectedLayer, fp).commandCount;
      } else {
        return frames[fp]->getSize();
      }
    }
    int getFrameCount() const {
      return frames.size();
    }

    // Return the command list in JSON representation as a string
    std::string jsonCommandList(sk_sp<SkSurface> surface) {
      SkDynamicMemoryWStream stream;
      SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
      writer.beginObject(); // root
      visibleCanvas()->toJSON(writer, udm, surface->getCanvas());
      writer.endObject(); // root
      writer.flush();
      auto skdata = stream.detachAsData();
      // Convert skdata to string_view, which accepts a length
      std::string_view data_view(reinterpret_cast<const char*>(skdata->data()), skdata->size());
      // and string_view to string, which emscripten understands.
      return std::string(data_view);
    }

    // Gets the clip and matrix of the last command drawn
    std::string lastCommandInfo() {
      SkM44 vm = visibleCanvas()->getCurrentMatrix();
      SkIRect clip = visibleCanvas()->getCurrentClip();

      SkDynamicMemoryWStream stream;
      SkJSONWriter writer(&stream, SkJSONWriter::Mode::kFast);
      writer.beginObject(); // root

      writer.appendName("ViewMatrix");
      DrawCommand::MakeJsonMatrix44(writer, vm);
      writer.appendName("ClipRect");
      DrawCommand::MakeJsonIRect(writer, clip);

      writer.endObject(); // root
      writer.flush();
      auto skdata = stream.detachAsData();
      // Convert skdata to string_view, which accepts a length
      std::string_view data_view(reinterpret_cast<const char*>(skdata->data()), skdata->size());
      // and string_view to string, which emscripten understands.
      return std::string(data_view);
    }

    void changeFrame(int index) {
      fp = index;
    }

    // Return the png file at the requested index in
    // the skp file's vector of shared images. this is the set of images referred to by the
    // filenames like "\\1" in DrawImage commands.
    // Return type is the PNG data as a base64 encoded string with prepended URI.
    std::string getImageResource(int index) {
      sk_sp<SkData> pngData = SkPngEncoder::Encode(nullptr, fImages[index].get(), {});
      size_t len = SkBase64::EncodedSize(pngData->size());
      SkString dst;
      dst.resize(len);
      SkBase64::Encode(pngData->data(), pngData->size(), dst.data());
      dst.prepend("data:image/png;base64,");
      return std::string(dst.c_str());
    }

    int getImageCount() {
      return fImages.size();
    }

    // Get the image info of one of the resource images.
    ImageInfoNoColorspace getImageInfo(int index) {
      return toImageInfoNoColorspace(fImages[index]->imageInfo());
    }

    // return data on which commands each image is used in.
    // (frame, -1) returns info for the given frame,
    // (frame, nodeid) return info for a layer update
    // { imageid: [commandid, commandid, ...], ... }
    JSObject imageUseInfo(int framenumber, int nodeid) {
      JSObject result = emscripten::val::object();
      DebugCanvas* debugCanvas = frames[framenumber].get();
      if (nodeid >= 0) {
        debugCanvas = fLayerManager->getEventDebugCanvas(nodeid, framenumber);
      }
      const auto& map = debugCanvas->getImageIdToCommandMap(udm);
      for (auto it = map.begin(); it != map.end(); ++it) {
        JSArray list = emscripten::val::array();
        for (const int commandId : it->second) {
          list.call<void>("push", commandId);
        }
        result.set(std::to_string(it->first), list);
      }
      return result;
    }

    // Return information on every layer (offscreeen buffer) that is available for drawing at
    // the current frame.
    JSArray getLayerSummariesJs() {
      JSArray result = emscripten::val::array();
      for (auto summary : fLayerManager->summarizeLayers(fp)) {
          result.call<void>("push", summary);
      }
      return result;
    }

    JSArray getLayerKeys() {
      JSArray result = emscripten::val::array();
      for (auto key : fLayerManager->getKeys()) {
        JSObject item = emscripten::val::object();
        item.set("frame", key.frame);
        item.set("nodeId", key.nodeId);
        result.call<void>("push", item);
      }
      return result;
    }

    // When set to a valid layer index, causes this class to playback the layer draw event at nodeId
    // on frame fp. No validation of nodeId or fp is performed, this must be valid values obtained
    // from either fLayerManager.listNodesForFrame or fLayerManager.summarizeEvents
    // Set to -1 to return to viewing the top level animation
    void setInspectedLayer(int nodeId) {
      fInspectedLayer = nodeId;
    }

    // Finds a command that left the given pixel in it's current state.
    // Note that this method may fail to find the absolute last command that leaves a pixel
    // the given color, but there is probably only one candidate in most cases, and the log(n)
    // makes it worth it.
    int findCommandByPixel(SkSurface* surface, int x, int y, int commandIndex) {
      // What color is the pixel now?
      SkColor finalColor = evaluateCommandColor(surface, commandIndex, x, y);

      int lowerBound = 0;
      int upperBound = commandIndex;

      while (upperBound - lowerBound > 1) {
        int command = (upperBound - lowerBound) / 2 + lowerBound;
        auto c = evaluateCommandColor(surface, command, x, y);
        if (c == finalColor) {
          upperBound = command;
        } else {
          lowerBound = command;
        }
      }
      // clean up after side effects
      drawTo(surface, commandIndex);
      return upperBound;
    }

  private:

      // Helper for findCommandByPixel.
      // Has side effect of flushing to surface.
      // TODO(nifong) eliminate side effect.
      SkColor evaluateCommandColor(SkSurface* surface, int command, int x, int y) {
        drawTo(surface, command);

        SkColor c;
        SkImageInfo info = SkImageInfo::Make(1, 1, kRGBA_8888_SkColorType, kOpaque_SkAlphaType);
        SkPixmap pixmap(info, &c, 4);
        surface->readPixels(pixmap, x, y);
        return c;
      }

      // Loads a single frame (traditional) skp file from the provided data stream and returns
      // a newly allocated DebugCanvas initialized with the SkPicture that was in the file.
      std::unique_ptr<DebugCanvas> loadSingleFrame(SkMemoryStream* stream) {
        register_typeface();
        SkDeserialProcs procs;
        procs.fImageDataProc = deserializeImage;
        sk_sp<SkFontMgr> fallback = SkFontMgr_New_Custom_Empty();
        procs.fTypefaceCtx = &fallback;
        procs.fTypefaceStreamProc = deserializeTypeface;
        sk_sp<SkPicture> picture = SkPicture::MakeFromStream(stream, &procs);
        if (!picture) {
          SkDebugf("Unable to deserialze frame.\n");
          return nullptr;
        }
        SkDebugf("Parsed SKP file.\n");
        // Make debug canvas using bounds from SkPicture
        fBoundsArray.push_back(picture->cullRect().roundOut());
        std::unique_ptr<DebugCanvas> debugCanvas = std::make_unique<DebugCanvas>(fBoundsArray.back());

        // Only draw picture to the debug canvas once.
        debugCanvas->drawPicture(picture);
        return debugCanvas;
      }

      std::string loadMultiFrame(SkMemoryStream* stream) {
        register_typeface();
        // Attempt to deserialize with an image sharing serial proc.
        auto deserialContext = std::make_unique<SkSharingDeserialContext>();
        SkDeserialProcs procs;
        procs.fImageProc = SkSharingDeserialContext::deserializeImage;
        procs.fImageCtx = deserialContext.get();
        sk_sp<SkFontMgr> fallback = SkFontMgr_New_Custom_Empty();
        procs.fTypefaceCtx = &fallback;
        procs.fTypefaceStreamProc = deserializeTypeface;

        int page_count = SkMultiPictureDocument::ReadPageCount(stream);
        if (!page_count) {
          // MSKP's have a version separate from the SKP subpictures they contain.
          return "Not a MultiPictureDocument, MultiPictureDocument file version too old, or MultiPictureDocument contained 0 frames.";
        }
        SkDebugf("Expecting %d frames\n", page_count);

        std::vector<SkDocumentPage> pages(page_count);
        if (!SkMultiPictureDocument::Read(stream, pages.data(), page_count, &procs)) {
          return "Reading frames from MultiPictureDocument failed";
        }

        fLayerManager = std::make_unique<DebugLayerManager>();

        int i = 0;
        for (const auto& page : pages) {
          // Make debug canvas using bounds from SkPicture
          fBoundsArray.push_back(page.fPicture->cullRect().roundOut());
          std::unique_ptr<DebugCanvas> debugCanvas = std::make_unique<DebugCanvas>(fBoundsArray.back());
          debugCanvas->setLayerManagerAndFrame(fLayerManager.get(), i);

          // Only draw picture to the debug canvas once.
          debugCanvas->drawPicture(page.fPicture);

          if (debugCanvas->getSize() <=0 ){
            SkDebugf("Skipped corrupted frame, had %d commands \n", debugCanvas->getSize());
            continue;
          }
          // If you don't set these, they're undefined.
          debugCanvas->setOverdrawViz(false);
          debugCanvas->setDrawGpuOpBounds(false);
          debugCanvas->setClipVizColor(SK_ColorTRANSPARENT);
          debugCanvas->setAndroidClipViz(false);
          frames.push_back(std::move(debugCanvas));
          i++;
        }
        fImages = deserialContext->fImages;

        udm.indexImages(fImages);
        return "";
      }

      // constrains the draw command index to the frame's command list length.
      int constrainFrameCommand(int index) {
        int cmdlen = frames[fp]->getSize();
        if (index >= cmdlen) {
          return cmdlen-1;
        }
        return index;
      }

      // A vector of DebugCanvas, each one initialized to a frame of the animation.
      std::vector<std::unique_ptr<DebugCanvas>> frames;
      // The index of the current frame (into the vector above)
      int fp = 0;
      // The width and height of every frame.
      // frame sizes are known to change in Android Skia RenderEngine because it interleves pictures from different applications.
      std::vector<SkIRect> fBoundsArray;
      // image resources from a loaded file
      std::vector<sk_sp<SkImage>> fImages;

      // The URLDataManager here is a cache that accepts encoded data (pngs) and puts
      // numbers on them. We have our own collection of images (fImages) that was populated by the
      // SkSharingDeserialContext when mskp files are loaded which it can use for IDing images
      // without having to serialize them.
      UrlDataManager udm;

      // A structure holding the picture information needed to draw any layers used in an mskp file
      // individual frames hold a pointer to it, store draw events, and request images from it.
      // it is stateful and is set to the current frame at all times.
      std::unique_ptr<DebugLayerManager> fLayerManager;

      // The node id of a layer being inspected, if any.
      // -1 means we are viewing the top level animation, not a layer.
      // the exact draw event being inspected depends also on the selected frame `fp`.
      int fInspectedLayer = -1;
};

using namespace emscripten;
EMSCRIPTEN_BINDINGS(my_module) {

  function("MinVersion", &MinVersion);

  // The main class that the JavaScript in index.html uses
  class_<SkpDebugPlayer>("SkpDebugPlayer")
    .constructor<>()
    .function("changeFrame",          &SkpDebugPlayer::changeFrame)
    .function("deleteCommand",        &SkpDebugPlayer::deleteCommand)
    .function("draw",                 &SkpDebugPlayer::draw, allow_raw_pointers())
    .function("drawTo",               &SkpDebugPlayer::drawTo, allow_raw_pointers())
    .function("findCommandByPixel",   &SkpDebugPlayer::findCommandByPixel, allow_raw_pointers())
    .function("getBounds",            &SkpDebugPlayer::getBounds)
    .function("getBoundsForFrame",    &SkpDebugPlayer::getBoundsForFrame)
    .function("getFrameCount",        &SkpDebugPlayer::getFrameCount)
    .function("getImageResource",     &SkpDebugPlayer::getImageResource)
    .function("getImageCount",        &SkpDebugPlayer::getImageCount)
    .function("getImageInfo",         &SkpDebugPlayer::getImageInfo)
    .function("getLayerKeys",         &SkpDebugPlayer::getLayerKeys)
    .function("getLayerSummariesJs",  &SkpDebugPlayer::getLayerSummariesJs)
    .function("getSize",              &SkpDebugPlayer::getSize)
    .function("imageUseInfo",         &SkpDebugPlayer::imageUseInfo)
    .function("imageUseInfoForFrameJs", optional_override([](SkpDebugPlayer& self, const int frame)->JSObject {
       // -1 as a node id is used throughout the application to mean no layer inspected.
      return self.imageUseInfo(frame, -1);
    }))
    .function("jsonCommandList",      &SkpDebugPlayer::jsonCommandList, allow_raw_pointers())
    .function("lastCommandInfo",      &SkpDebugPlayer::lastCommandInfo)
    .function("loadSkp",              &SkpDebugPlayer::loadSkp, allow_raw_pointers())
    .function("setClipVizColor",      &SkpDebugPlayer::setClipVizColor)
    .function("setCommandVisibility", &SkpDebugPlayer::setCommandVisibility)
    .function("setGpuOpBounds",       &SkpDebugPlayer::setGpuOpBounds)
    .function("setInspectedLayer",    &SkpDebugPlayer::setInspectedLayer)
    .function("setOriginVisible",     &SkpDebugPlayer::setOriginVisible)
    .function("setOverdrawVis",       &SkpDebugPlayer::setOverdrawVis)
    .function("setAndroidClipViz",    &SkpDebugPlayer::setAndroidClipViz);

  // Structs used as arguments or returns to the functions above
  // TODO(kjlubick) handle this rect like the ones in CanvasKit
  value_object<SkIRect>("SkIRect")
      .field("fLeft",   &SkIRect::fLeft)
      .field("fTop",    &SkIRect::fTop)
      .field("fRight",  &SkIRect::fRight)
      .field("fBottom", &SkIRect::fBottom);
  // emscripten provided the following convenience function for binding vector<T>
  // https://emscripten.org/docs/api_reference/bind.h.html#_CPPv415register_vectorPKc
  register_vector<DebugLayerManager::LayerSummary>("VectorLayerSummary");
  value_object<DebugLayerManager::LayerSummary>("LayerSummary")
    .field("nodeId",            &DebugLayerManager::LayerSummary::nodeId)
    .field("frameOfLastUpdate", &DebugLayerManager::LayerSummary::frameOfLastUpdate)
    .field("fullRedraw",        &DebugLayerManager::LayerSummary::fullRedraw)
    .field("layerWidth",        &DebugLayerManager::LayerSummary::layerWidth)
    .field("layerHeight",       &DebugLayerManager::LayerSummary::layerHeight);

  value_object<ImageInfoNoColorspace>("ImageInfoNoColorspace")
    .field("width",     &ImageInfoNoColorspace::width)
    .field("height",    &ImageInfoNoColorspace::height)
    .field("colorType", &ImageInfoNoColorspace::colorType)
    .field("alphaType", &ImageInfoNoColorspace::alphaType);
}
