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

#include <set>
#include <string>
#include <emscripten.h>
#include <emscripten/bind.h>
#include <emscripten/html5.h>

#include "gm/gm.h"
#include "include/core/SkBitmap.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkData.h"
#include "include/core/SkImageInfo.h"
#include "include/core/SkStream.h"
#include "include/core/SkSurface.h"
#include "include/gpu/GrContextOptions.h"
#include "include/gpu/GrDirectContext.h"
#include "include/gpu/gl/GrGLInterface.h"
#include "include/gpu/gl/GrGLTypes.h"
#include "modules/canvaskit/WasmCommon.h"
#include "src/core/SkFontMgrPriv.h"
#include "src/core/SkMD5.h"
#include "tests/Test.h"
#include "tools/HashAndEncode.h"
#include "tools/ResourceFactory.h"
#include "tools/flags/CommandLineFlags.h"
#include "tools/fonts/TestFontMgr.h"

using namespace emscripten;

/**
 * Returns a JS array of strings containing the names of the registered GMs. GMs are only registered
 * when their source is included in the "link" step, not if they are in something like libgm.a.
 * The names are also logged to the console.
 */
static JSArray ListGMs() {
    SkDebugf("Listing GMs\n");
    JSArray gms = emscripten::val::array();
    for (skiagm::GMFactory fact : skiagm::GMRegistry::Range()) {
        std::unique_ptr<skiagm::GM> gm(fact());
        SkDebugf("gm %s\n", gm->getName());
        gms.call<void>("push", std::string(gm->getName()));
    }
    return gms;
}

static std::unique_ptr<skiagm::GM> getGMWithName(std::string name) {
    for (skiagm::GMFactory fact : skiagm::GMRegistry::Range()) {
        std::unique_ptr<skiagm::GM> gm(fact());
        if (gm->getName() == name) {
            return gm;
        }
    }
    return nullptr;
}

/**
 * Sets the given WebGL context to be "current" and then creates a GrDirectContext from that
 * context.
 */
static sk_sp<GrDirectContext> MakeGrContext(EMSCRIPTEN_WEBGL_CONTEXT_HANDLE context)
{
    EMSCRIPTEN_RESULT r = emscripten_webgl_make_context_current(context);
    if (r < 0) {
        printf("failed to make webgl context current %d\n", r);
        return nullptr;
    }
    // setup GrDirectContext
    auto interface = GrGLMakeNativeInterface();
    // setup contexts
    sk_sp<GrDirectContext> dContext(GrDirectContext::MakeGL(interface));
    return dContext;
}

static std::set<std::string> gKnownDigests;

static void LoadKnownDigest(std::string md5) {
  gKnownDigests.insert(md5);
}

static std::map<std::string, sk_sp<SkData>> gResources;

static sk_sp<SkData> getResource(const char* name) {
  auto it = gResources.find(name);
  if (it == gResources.end()) {
    SkDebugf("Resource %s not found\n", name);
    return nullptr;
  }
  return it->second;
}

static void LoadResource(std::string name, uintptr_t /* byte* */ bPtr, size_t len) {
  const uint8_t* bytes = reinterpret_cast<const uint8_t*>(bPtr);
  auto data = SkData::MakeFromMalloc(bytes, len);
  gResources[name] = std::move(data);

  if (!gResourceFactory) {
    gResourceFactory = getResource;
  }
}

/**
 * Runs the given GM and returns a JS object. If the GM was successful, the object will have the
 * following properties:
 *   "png" - a Uint8Array of the PNG data extracted from the surface.
 *   "hash" - a string which is the md5 hash of the pixel contents and the metadata.
 */
static JSObject RunGM(sk_sp<GrDirectContext> ctx, std::string name) {
    JSObject result = emscripten::val::object();
    auto gm = getGMWithName(name);
    if (!gm) {
        SkDebugf("Could not find gm with name %s\n", name.c_str());
        return result;
    }
    // TODO(kjlubick) make these configurable somehow. This probably makes sense to do as function
    //   parameters.
    auto alphaType = SkAlphaType::kPremul_SkAlphaType;
    auto colorType = SkColorType::kN32_SkColorType;
    SkISize size = gm->getISize();
    SkImageInfo info = SkImageInfo::Make(size, colorType, alphaType);
    sk_sp<SkSurface> surface(SkSurface::MakeRenderTarget(ctx.get(),
                             SkBudgeted::kYes,
                             info, 0,
                             kBottomLeft_GrSurfaceOrigin,
                             nullptr, true));
    if (!surface) {
        SkDebugf("Could not make surface\n");
        return result;
    }
    auto canvas = surface->getCanvas();

    gm->onceBeforeDraw();
    SkString msg;
    // Based on GMSrc::draw from DM.
    auto gpuSetupResult = gm->gpuSetup(ctx.get(), canvas, &msg);
    if (gpuSetupResult == skiagm::DrawResult::kFail) {
        SkDebugf("Error with gpu setup for gm %s: %s\n", name.c_str(), msg.c_str());
        return result;
    } else if (gpuSetupResult == skiagm::DrawResult::kSkip) {
        return result;
    }

    auto drawResult = gm->draw(canvas, &msg);
    if (drawResult == skiagm::DrawResult::kFail) {
        SkDebugf("Error with gm %s: %s\n", name.c_str(), msg.c_str());
        return result;
    } else if (drawResult == skiagm::DrawResult::kSkip) {
        return result;
    }
    surface->flushAndSubmit(true);

    // Based on GPUSink::readBack
    SkBitmap bitmap;
    bitmap.allocPixels(info);
    if (!canvas->readPixels(bitmap, 0, 0)) {
        SkDebugf("Could not read pixels back\n");
        return result;
    }

    // Now we need to encode to PNG and get the md5 hash of the pixels (and colorspace and stuff).
    // This is based on Task::Run from DM.cpp
    std::unique_ptr<HashAndEncode> hashAndEncode = std::make_unique<HashAndEncode>(bitmap);
    SkString md5;
    SkMD5 hash;
    hashAndEncode->feedHash(&hash);
    SkMD5::Digest digest = hash.finish();
    for (int i = 0; i < 16; i++) {
        md5.appendf("%02x", digest.data[i]);
    }

    auto ok = gKnownDigests.find(md5.c_str());
    if (ok == gKnownDigests.end()) {
        // We only need to decode the image if it is "interesting", that is, we have not written it
        // before to disk and uploaded it to gold.
        SkDynamicMemoryWStream stream;
        // We do not need to include the keys because they are optional - they are not read by Gold.
        CommandLineFlags::StringArray empty;
        hashAndEncode->encodePNG(&stream, md5.c_str(), empty, empty);

        auto data = stream.detachAsData();

        // This is the cleanest way to create a new Uint8Array with a copy of the data that is not
        // in the WASM heap. kjlubick tried returning a pointer inside an SkData, but that lead to
        // some use after free issues. By making the copy using the JS transliteration, we don't
        // risk the SkData object being cleaned up before we make the copy.
        Uint8Array pngData = emscripten::val(
            // https://emscripten.org/docs/porting/connecting_cpp_and_javascript/embind.html#memory-views
            typed_memory_view(data->size(), data->bytes())
        ).call<Uint8Array>("slice"); // slice with no args makes a copy of the memory view.

        result.set("png", pngData);
        gKnownDigests.emplace(md5.c_str());
    }
    result.set("hash", md5.c_str());
    return result;
}

static JSArray ListTests() {
    SkDebugf("Listing Tests\n");
    JSArray tests = emscripten::val::array();
    for (auto test : skiatest::TestRegistry::Range()) {
        SkDebugf("test %s\n", test.name);
        tests.call<void>("push", std::string(test.name));
    }
    return tests;
}

static skiatest::Test getTestWithName(std::string name, bool* ok) {
    for (auto test : skiatest::TestRegistry::Range()) {
        if (name == test.name) {
          *ok = true;
          return test;
        }
    }
    *ok = false;
    return skiatest::Test(nullptr, false, nullptr);
}

// Based on DM.cpp:run_test
struct WasmReporter : public skiatest::Reporter {
    WasmReporter(std::string name, JSObject result): fName(name), fResult(result){}

    void reportFailed(const skiatest::Failure& failure) override {
        SkDebugf("Test %s failed: %s\n", fName.c_str(), failure.toString().c_str());
        fResult.set("result", "failed");
        fResult.set("msg", failure.toString().c_str());
    }
    std::string fName;
    JSObject fResult;
};

/**
 * Runs the given Test and returns a JS object. If the Test was located, the object will have the
 * following properties:
 *   "result" : One of "passed", "failed", "skipped".
 *   "msg": May be non-empty on failure
 */
static JSObject RunTest(std::string name) {
    JSObject result = emscripten::val::object();
    bool ok = false;
    auto test = getTestWithName(name, &ok);
    if (!ok) {
        SkDebugf("Could not find test with name %s\n", name.c_str());
        return result;
    }
    GrContextOptions grOpts;
    if (test.needsGpu) {
        result.set("result", "passed"); // default to passing - the reporter will mark failed.
        WasmReporter reporter(name, result);
        test.run(&reporter, grOpts);
        return result;
    }

    result.set("result", "passed"); // default to passing - the reporter will mark failed.
    WasmReporter reporter(name, result);
    test.run(&reporter, grOpts);
    return result;
}

namespace skiatest {

class WasmContextInfo : public sk_gpu_test::ContextInfo {
public:
    WasmContextInfo(GrDirectContext* context,
                    const GrContextOptions& options)
          : fContext(context), fOptions(options) {}

    GrDirectContext* directContext() const { return fContext; }
    sk_gpu_test::TestContext* testContext() const { return nullptr; }

    sk_gpu_test::GLTestContext* glContext() const { return nullptr; }

    const GrContextOptions& options() const { return fOptions; }
private:
    GrDirectContext* fContext = nullptr;
    GrContextOptions fOptions;
};

using ContextType = sk_gpu_test::GrContextFactory::ContextType;

// These are the supported GrContextTypeFilterFn
bool IsGLContextType(ContextType ct) {
    return GrBackendApi::kOpenGL == sk_gpu_test::GrContextFactory::ContextTypeBackend(ct);
}
bool IsRenderingGLContextType(ContextType ct) {
    return IsGLContextType(ct) && sk_gpu_test::GrContextFactory::IsRenderingContext(ct);
}
bool IsRenderingGLOrMetalContextType(ContextType ct) {
    return IsRenderingGLContextType(ct);
}
bool IsMockContextType(ContextType ct) {
    return ct == ContextType::kMock_ContextType;
}
// These are not supported
bool IsVulkanContextType(ContextType) {return false;}
bool IsMetalContextType(ContextType) {return false;}
bool IsDirect3DContextType(ContextType) {return false;}
bool IsDawnContextType(ContextType) {return false;}

void RunWithGPUTestContexts(GrContextTestFn* test, GrContextTypeFilterFn* contextTypeFilter,
                            Reporter* reporter, const GrContextOptions& options) {
    for (auto contextType : {ContextType::kGLES_ContextType, ContextType::kMock_ContextType}) {
        if (contextTypeFilter && !(*contextTypeFilter)(contextType)) {
            continue;
        }
        sk_sp<GrDirectContext> ctx = (contextType == ContextType::kGLES_ContextType) ?
                                     GrDirectContext::MakeGL(options) :
                                     GrDirectContext::MakeMock(nullptr, options);
        if (!ctx) {
            SkDebugf("Could not make context\n");
            return;
        }
        WasmContextInfo ctxInfo(ctx.get(), options);

        // From DMGpuTestProcs.cpp
        (*test)(reporter, ctxInfo);
        // Sync so any release/finished procs get called.
        ctxInfo.directContext()->flushAndSubmit(/*sync*/true);
    }
}
} // namespace skiatest

namespace sk_gpu_test {
GLTestContext *CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
                                           GLTestContext *shareContext) {
    return nullptr;
}
} // namespace sk_gpu_test

void Init() {
    // Use the portable fonts.
    gSkFontMgr_DefaultFactory = &ToolUtils::MakePortableFontMgr;
}

EMSCRIPTEN_BINDINGS(GMs) {
    function("Init", &Init);
    function("ListGMs", &ListGMs);
    function("ListTests", &ListTests);
    function("LoadKnownDigest", &LoadKnownDigest);
    function("_LoadResource", &LoadResource);
    function("MakeGrContext", &MakeGrContext);
    function("RunGM", &RunGM);
    function("RunTest", &RunTest);

    class_<GrDirectContext>("GrDirectContext")
        .smart_ptr<sk_sp<GrDirectContext>>("sk_sp<GrDirectContext>");
}
