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

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 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_gpu_test::GrContextFactory factory(options);
        sk_gpu_test::ContextInfo ctxInfo = factory.getContextInfo(contextType);

        REPORTER_ASSERT(reporter, ctxInfo.directContext() != nullptr);
        if (!ctxInfo.directContext()) {
            return;
        }
        ctxInfo.testContext()->makeCurrent();
        // From DMGpuTestProcs.cpp
        (*test)(reporter, ctxInfo);
        // Sync so any release/finished procs get called.
        ctxInfo.directContext()->flushAndSubmit(/*sync*/true);
    }
}
} // namespace skiatest

namespace {

// A GLtestContext that we can return from CreatePlatformGLTestContext below.
// It doesn't have to do anything WebGL-specific that I know of but we can't return
// a GLTestContext because it has pure virtual methods that need to be implemented.
class WasmWebGlTestContext : public sk_gpu_test::GLTestContext {
public:
    WasmWebGlTestContext() {}
    ~WasmWebGlTestContext() override {
        this->teardown();
    }
    // We assume WebGL only has one context and that it is always current.
    // Therefore these context related functions return null intentionally.
    // It's possible that more tests will pass if these were correctly implemented.
    std::unique_ptr<GLTestContext> makeNew() const override {
        // This is supposed to create a new GL context in a new GLTestContext.
        // Specifically for tests that do not want to re-use the existing one.
        return nullptr;
    }
    void onPlatformMakeNotCurrent() const override { }
    void onPlatformMakeCurrent() const override { }
    std::function<void()> onPlatformGetAutoContextRestore() const override {
        return nullptr;
    }
    GrGLFuncPtr onPlatformGetProcAddress(const char* procName) const override {
        return nullptr;
    }
};
} // namespace

namespace sk_gpu_test {
GLTestContext *CreatePlatformGLTestContext(GrGLStandard forcedGpuAPI,
                                           GLTestContext *shareContext) {
    return new WasmWebGlTestContext();
}
} // 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>");
}
