// 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 "experimental/svg/model/SkSVGDOM.h"
#include "gm/gm.h"
#include "include/codec/SkCodec.h"
#include "include/core/SkColorSpace.h"
#include "include/core/SkGraphics.h"
#include "include/core/SkPicture.h"
#include "include/core/SkPictureRecorder.h"
#include "include/docs/SkPDFDocument.h"
#include "include/gpu/GrContextOptions.h"
#include "include/private/SkTHash.h"
#include "src/core/SkColorSpacePriv.h"
#include "src/core/SkMD5.h"
#include "src/core/SkOSFile.h"
#include "src/gpu/GrContextPriv.h"
#include "src/gpu/GrGpu.h"
#include "src/utils/SkOSPath.h"
#include "tests/Test.h"
#include "tools/AutoreleasePool.h"
#include "tools/CrashHandler.h"
#include "tools/HashAndEncode.h"
#include "tools/ToolUtils.h"
#include "tools/flags/CommandLineFlags.h"
#include "tools/flags/CommonFlags.h"
#include "tools/gpu/GrContextFactory.h"
#include "tools/gpu/MemoryCache.h"
#include "tools/trace/EventTracingPriv.h"
#include <chrono>
#include <functional>
#include <stdio.h>
#include <stdlib.h>

#if defined(SK_ENABLE_SKOTTIE)
    #include "modules/skottie/include/Skottie.h"
    #include "modules/skresources/include/SkResources.h"
#endif

using sk_gpu_test::GrContextFactory;

static DEFINE_bool(listGMs  , false, "Print GM names and exit.");
static DEFINE_bool(listTests, false, "Print unit test names and exit.");

static DEFINE_string2(sources, s, "", "Which GMs, .skps, or images to draw.");
static DEFINE_string2(backend, b, "", "Backend used to create a canvas to draw into.");

static DEFINE_string(ct    ,   "8888", "The color type for any raster backend.");
static DEFINE_string(at    , "premul", "The alpha type for any raster backend.");
static DEFINE_string(gamut ,   "srgb", "The color gamut for any raster backend.");
static DEFINE_string(tf    ,   "srgb", "The transfer function for any raster backend.");
static DEFINE_bool  (legacy,    false, "Use a null SkColorSpace instead of --gamut and --tf?");
static DEFINE_bool  (skvm  ,    false, "Use SkVMBlitter when supported?");
static DEFINE_bool  (dylib ,    false, "Use SkVM via dylib?");

static DEFINE_int   (samples ,         0, "Samples per pixel in GPU backends.");
static DEFINE_bool  (stencils,      true, "If false, avoid stencil buffers in GPU backends.");
static DEFINE_bool  (dit     ,     false, "Use device-independent text in GPU backends.");
static DEFINE_string(surf    , "default", "Backing store for GPU backend surfaces.");

static DEFINE_bool(       preAbandonGpuContext, false, "Abandon the GrContext before drawing.");
static DEFINE_bool(          abandonGpuContext, false, "Abandon the GrContext after drawing.");
static DEFINE_bool(releaseAndAbandonGpuContext, false,
                   "Release all GPU resources and abandon the GrContext after drawing.");

static DEFINE_bool(decodeToDst, false,
                   "Decode images to destination format rather than suggested natural format.");

static DEFINE_double(rasterDPI, SK_ScalarDefaultRasterDPI,
                     "DPI for rasterized content in vector backends like --backend pdf.");
static DEFINE_bool(PDFA, false, "Create PDF/A with --backend pdf?");

static DEFINE_bool   (cpuDetect, true, "Detect CPU features for runtime optimizations?");
static DEFINE_string2(writePath, w, "", "Write .pngs to this directory if set.");
static DEFINE_bool   (quick, false, "Skip image hashing and encoding?");

static DEFINE_string(writeShaders, "", "Write GLSL shaders to this directory if set.");

static DEFINE_string(key,        "", "Metadata passed through to .png encoder and .json output.");
static DEFINE_string(properties, "", "Metadata passed through to .png encoder and .json output.");

template <typename T>
struct FlagOption {
    const char* label;
    T           value;
};

template <typename T, int N>
static bool parse_flag(const CommandLineFlags::StringArray& flag,
                       const char* flag_name,
                       const FlagOption<T> (&array)[N],
                       T* value) {
    for (auto entry : array) {
        if (flag.contains(entry.label)) {
            *value = entry.value;
            return true;
        }
    }
    fprintf(stderr, "Known values for --%s:\n", flag_name);
    for (auto entry : array) {
        fprintf(stderr, "    --%s %s\n", flag_name, entry.label);
    }
    return false;
}

struct Result {
    enum { Ok, Skip, Fail} status;
    SkString               failure;
};
static const Result ok = {Result::Ok,   {}},
                  skip = {Result::Skip, {}};

template <typename... Args>
static Result fail(const char* why, Args... args) {
    return { Result::Fail, SkStringPrintf(why, args...) };
}


struct Source {
    SkString                               name;
    SkISize                                size;
    std::function<Result(SkCanvas*)>       draw;
    std::function<void(GrContextOptions*)> tweak = [](GrContextOptions*){};
};

static void init(Source* source, std::shared_ptr<skiagm::GM> gm) {
    source->size  = gm->getISize();
    source->tweak = [gm](GrContextOptions* options) { gm->modifyGrContextOptions(options); };
    source->draw  = [gm](SkCanvas* canvas) {
        SkString err;
        switch (gm->draw(canvas, &err)) {
            case skiagm::DrawResult::kOk:   break;
            case skiagm::DrawResult::kSkip: return skip;
            case skiagm::DrawResult::kFail: return fail(err.c_str());
        }
        return ok;
    };
}

static void init(Source* source, sk_sp<SkPicture> pic) {
    source->size = pic->cullRect().roundOut().size();
    source->draw = [pic](SkCanvas* canvas) {
        canvas->drawPicture(pic);
        return ok;
    };
}

static void init(Source* source, std::shared_ptr<SkCodec> codec) {
    source->size = codec->dimensions();
    source->draw = [codec](SkCanvas* canvas) {
        SkImageInfo info = codec->getInfo();
        if (FLAGS_decodeToDst) {
            info = canvas->imageInfo().makeDimensions(info.dimensions());
        }

        SkBitmap bm;
        bm.allocPixels(info);
        switch (SkCodec::Result result = codec->getPixels(info, bm.getPixels(), bm.rowBytes())) {
            case SkCodec::kSuccess:
            case SkCodec::kErrorInInput:
            case SkCodec::kIncompleteInput: canvas->drawBitmap(bm, 0,0);
                                            break;
            default: return fail("codec->getPixels() failed: %d\n", result);
        }
        return ok;
    };
}

static void init(Source* source, sk_sp<SkSVGDOM> svg) {
    source->size = svg->containerSize().isEmpty() ? SkISize{1000,1000}
                                                  : svg->containerSize().toCeil();
    source->draw = [svg](SkCanvas* canvas) {
        svg->render(canvas);
        return ok;
    };
}

#if defined(SK_ENABLE_SKOTTIE)
static void init(Source* source, sk_sp<skottie::Animation> animation) {
    source->size = {1000,1000};
    source->draw = [animation](SkCanvas* canvas) {
        canvas->clear(SK_ColorWHITE);

        // Draw frames in a shuffled order to exercise nonlinear frame progression.
        // The film strip will still be in time order, just drawn out of order.
        const int order[] = { 4, 0, 3, 1, 2 };
        const int tiles = SK_ARRAY_COUNT(order);
        const float dim = 1000.0f / tiles;

        const float dt = 1.0f / (tiles*tiles - 1);

        for (int y : order)
        for (int x : order) {
            SkRect dst = {x*dim, y*dim, (x+1)*dim, (y+1)*dim};

            SkAutoCanvasRestore _(canvas, true/*save now*/);
            canvas->clipRect(dst, /*aa=*/true);
            canvas->concat(SkMatrix::MakeRectToRect(SkRect::MakeSize(animation->size()),
                                                    dst,
                                                    SkMatrix::kCenter_ScaleToFit));
            float t = (y*tiles + x) * dt;
            animation->seek(t);
            animation->render(canvas);
        }
        return ok;
    };
}
#endif

static void init(Source* source, const skiatest::Test& test) {
    source->size  = {1,1};
    source->draw  = [test](SkCanvas* canvas) {
        struct Reporter : public skiatest::Reporter {
            SkString msg;

            void reportFailed(const skiatest::Failure& failure) override {
                msg = failure.toString();
            }
        } reporter;

        test.run(&reporter, GrContextOptions{});

        if (reporter.msg.isEmpty()) {
            canvas->clear(SK_ColorGREEN);
            return ok;
        }

        canvas->clear(SK_ColorRED);
        return fail(reporter.msg.c_str());
    };
}

static sk_sp<SkImage> draw_with_cpu(std::function<bool(SkCanvas*)> draw,
                                    SkImageInfo info) {
    if (sk_sp<SkSurface> surface = SkSurface::MakeRaster(info)) {
        if (draw(surface->getCanvas())) {
            return surface->makeImageSnapshot();
        }
    }
    return nullptr;
}

static sk_sp<SkData> draw_as_skp(std::function<bool(SkCanvas*)> draw,
                                 SkImageInfo info) {
    SkPictureRecorder recorder;
    if (draw(recorder.beginRecording(info.width(), info.height()))) {
        return recorder.finishRecordingAsPicture()->serialize();
    }
    return nullptr;
}

static sk_sp<SkData> draw_as_pdf(std::function<bool(SkCanvas*)> draw,
                                 SkImageInfo info,
                                 SkString name) {
    SkPDF::Metadata metadata;
    metadata.fTitle     = name;
    metadata.fCreator   = "Skia/FM";
    metadata.fRasterDPI = FLAGS_rasterDPI;
    metadata.fPDFA      = FLAGS_PDFA;

    SkDynamicMemoryWStream stream;
    if (sk_sp<SkDocument> doc = SkPDF::MakeDocument(&stream, metadata)) {
        if (draw(doc->beginPage(info.width(), info.height()))) {
            doc->endPage();
            doc->close();
            return stream.detachAsData();
        }
    }
    return nullptr;
}

static sk_sp<SkImage> draw_with_gpu(std::function<bool(SkCanvas*)> draw,
                                    SkImageInfo info,
                                    GrContextFactory::ContextType api,
                                    GrContextFactory* factory) {
    enum class SurfaceType { kDefault, kBackendTexture, kBackendRenderTarget };
    const FlagOption<SurfaceType> kSurfaceTypes[] = {
        { "default", SurfaceType::kDefault },
        { "betex"  , SurfaceType::kBackendTexture },
        { "bert"   , SurfaceType::kBackendRenderTarget },
    };
    SurfaceType surfaceType;
    if (!parse_flag(FLAGS_surf, "surf", kSurfaceTypes, &surfaceType)) {
        return nullptr;
    }

    auto overrides = GrContextFactory::ContextOverrides::kNone;
    if (!FLAGS_stencils) { overrides |= GrContextFactory::ContextOverrides::kAvoidStencilBuffers; }

    GrContext* context = factory->getContextInfo(api, overrides)
                                 .grContext();

    uint32_t flags = FLAGS_dit ? SkSurfaceProps::kUseDeviceIndependentFonts_Flag
                               : 0;
    SkSurfaceProps props(flags, SkSurfaceProps::kLegacyFontHost_InitType);

    sk_sp<SkSurface> surface;
    GrBackendTexture backendTexture;
    GrBackendRenderTarget backendRT;

    switch (surfaceType) {
        case SurfaceType::kDefault:
            surface = SkSurface::MakeRenderTarget(context,
                                                  SkBudgeted::kNo,
                                                  info,
                                                  FLAGS_samples,
                                                  &props);
            break;

        case SurfaceType::kBackendTexture:
            backendTexture = context->createBackendTexture(info.width(),
                                                           info.height(),
                                                           info.colorType(),
                                                           GrMipMapped::kNo,
                                                           GrRenderable::kYes,
                                                           GrProtected::kNo);
            surface = SkSurface::MakeFromBackendTexture(context,
                                                        backendTexture,
                                                        kTopLeft_GrSurfaceOrigin,
                                                        FLAGS_samples,
                                                        info.colorType(),
                                                        info.refColorSpace(),
                                                        &props);
            break;

        case SurfaceType::kBackendRenderTarget:
            backendRT = context->priv().getGpu()
                ->createTestingOnlyBackendRenderTarget(info.width(),
                                                       info.height(),
                                                       SkColorTypeToGrColorType(info.colorType()));
            surface = SkSurface::MakeFromBackendRenderTarget(context,
                                                             backendRT,
                                                             kBottomLeft_GrSurfaceOrigin,
                                                             info.colorType(),
                                                             info.refColorSpace(),
                                                             &props);
            break;
    }

    if (!surface) {
        fprintf(stderr, "Could not create GPU surface.\n");
        return nullptr;
    }

    if (FLAGS_preAbandonGpuContext) {
        factory->abandonContexts();
    }

    sk_sp<SkImage> image;
    if (draw(surface->getCanvas())) {
        image = surface->makeImageSnapshot();
    }

    if (FLAGS_abandonGpuContext) {
        factory->abandonContexts();
    } else if (FLAGS_releaseAndAbandonGpuContext) {
        factory->releaseResourcesAndAbandonContexts();
    }

    if (!context->abandoned()) {
        surface.reset();
        if (backendTexture.isValid()) {
            context->deleteBackendTexture(backendTexture);
        }
        if (backendRT.isValid()) {
            context->priv().getGpu()->deleteTestingOnlyBackendRenderTarget(backendRT);
        }
    }

    return image;
}

extern bool gUseSkVMBlitter;
extern bool gSkVMJITViaDylib;

int main(int argc, char** argv) {
    CommandLineFlags::Parse(argc, argv);
    SetupCrashHandler();

    if (FLAGS_cpuDetect) {
        SkGraphics::Init();
    }
    gUseSkVMBlitter  = FLAGS_skvm;
    gSkVMJITViaDylib = FLAGS_dylib;

    initializeEventTracingForTools();
    ToolUtils::SetDefaultFontMgr();
    SetAnalyticAAFromCommonFlags();

    GrContextOptions baseOptions;
    SetCtxOptionsFromCommonFlags(&baseOptions);

    sk_gpu_test::MemoryCache memoryCache;
    if (!FLAGS_writeShaders.isEmpty()) {
        baseOptions.fPersistentCache = &memoryCache;
        baseOptions.fShaderCacheStrategy = GrContextOptions::ShaderCacheStrategy::kBackendSource;
    }

    SkTHashMap<SkString, skiagm::GMFactory> gm_factories;
    for (skiagm::GMFactory factory : skiagm::GMRegistry::Range()) {
        std::unique_ptr<skiagm::GM> gm{factory()};
        if (FLAGS_listGMs) {
            fprintf(stdout, "%s\n", gm->getName());
        } else {
            gm_factories.set(SkString{gm->getName()}, factory);
        }
    }

    SkTHashMap<SkString, const skiatest::Test*> tests;
    for (const skiatest::Test& test : skiatest::TestRegistry::Range()) {
        if (test.needsGpu) {
            continue;  // TODO
        }
        if (FLAGS_listTests) {
            fprintf(stdout, "%s\n", test.name);
        } else {
            tests.set(SkString{test.name}, &test);
        }
    }

    if (FLAGS_listGMs || FLAGS_listTests) {
        return 0;
    }
    if (FLAGS_sources.isEmpty()) {
        fprintf(stderr, "Please give me something to run using -s/--sources!\n");
        return 1;
    }

    SkTArray<Source> sources;
    for (const SkString& name : FLAGS_sources) {
        Source* source = &sources.push_back();

        if (skiagm::GMFactory* factory = gm_factories.find(name)) {
            std::shared_ptr<skiagm::GM> gm{(*factory)()};
            source->name = name;
            init(source, std::move(gm));
            continue;
        }

        if (const skiatest::Test** test = tests.find(name)) {
            source->name = name;
            init(source, **test);
            continue;
        }

        if (sk_sp<SkData> blob = SkData::MakeFromFileName(name.c_str())) {
            source->name = SkOSPath::Basename(name.c_str());

            if (name.endsWith(".skp")) {
                if (sk_sp<SkPicture> pic = SkPicture::MakeFromData(blob.get())) {
                    init(source, pic);
                    continue;
                }
            } else if (name.endsWith(".svg")) {
                SkMemoryStream stream{blob};
                if (sk_sp<SkSVGDOM> svg = SkSVGDOM::MakeFromStream(stream)) {
                    init(source, svg);
                    continue;
                }
            }
#if defined(SK_ENABLE_SKOTTIE)
            else if (name.endsWith(".json")) {
                const SkString dir  = SkOSPath::Dirname(name.c_str());
                if (sk_sp<skottie::Animation> animation = skottie::Animation::Builder()
                        .setResourceProvider(skresources::FileResourceProvider::Make(dir))
                        .make((const char*)blob->data(), blob->size())) {
                    init(source, animation);
                    continue;
                }
            }
#endif
            else if (std::shared_ptr<SkCodec> codec = SkCodec::MakeFromData(blob)) {
                init(source, codec);
                continue;
            }
        }

        fprintf(stderr, "Don't understand source '%s'... bailing out.\n", name.c_str());
        return 1;
    }

    enum NonGpuBackends {
        kCPU_Backend = -1,
        kSKP_Backend = -2,
        kPDF_Backend = -3,
    };
    const FlagOption<int> kBackends[] = {
        { "cpu"            , kCPU_Backend },
        { "skp"            , kSKP_Backend },
        { "pdf"            , kPDF_Backend },
        { "gl"             , GrContextFactory::kGL_ContextType },
        { "gles"           , GrContextFactory::kGLES_ContextType },
        { "angle_d3d9_es2" , GrContextFactory::kANGLE_D3D9_ES2_ContextType },
        { "angle_d3d11_es2", GrContextFactory::kANGLE_D3D11_ES2_ContextType },
        { "angle_d3d11_es3", GrContextFactory::kANGLE_D3D11_ES3_ContextType },
        { "angle_gl_es2"   , GrContextFactory::kANGLE_GL_ES2_ContextType },
        { "angle_gl_es3"   , GrContextFactory::kANGLE_GL_ES3_ContextType },
        { "commandbuffer"  , GrContextFactory::kCommandBuffer_ContextType },
        { "vk"             , GrContextFactory::kVulkan_ContextType },
        { "mtl"            , GrContextFactory::kMetal_ContextType },
        { "mock"           , GrContextFactory::kMock_ContextType },
    };
    const FlagOption<SkColorType> kColorTypes[] = {
        { "a8",           kAlpha_8_SkColorType },
        { "g8",            kGray_8_SkColorType },
        { "565",          kRGB_565_SkColorType },
        { "4444",       kARGB_4444_SkColorType },
        { "8888",             kN32_SkColorType },
        { "888x",        kRGB_888x_SkColorType },
        { "1010102", kRGBA_1010102_SkColorType },
        { "101010x",  kRGB_101010x_SkColorType },
        { "f16norm", kRGBA_F16Norm_SkColorType },
        { "f16",         kRGBA_F16_SkColorType },
        { "f32",         kRGBA_F32_SkColorType },
        { "rgba",       kRGBA_8888_SkColorType },
        { "bgra",       kBGRA_8888_SkColorType },
    };
    const FlagOption<SkAlphaType> kAlphaTypes[] = {
        {   "premul",   kPremul_SkAlphaType },
        { "unpremul", kUnpremul_SkAlphaType },
    };
    const FlagOption<skcms_Matrix3x3> kGamuts[] = {
        { "srgb",    SkNamedGamut::kSRGB },
        { "p3",      SkNamedGamut::kDisplayP3 },
        { "rec2020", SkNamedGamut::kRec2020 },
        { "adobe",   SkNamedGamut::kAdobeRGB },
        { "narrow",  gNarrow_toXYZD50},
    };
    const FlagOption<skcms_TransferFunction> kTransferFunctions[] = {
        { "srgb"   , SkNamedTransferFn::kSRGB },
        { "rec2020", SkNamedTransferFn::kRec2020 },
        { "2.2"    , SkNamedTransferFn::k2Dot2 },
        { "linear" , SkNamedTransferFn::kLinear },
    };


    int                      backend;
    SkColorType              ct;
    SkAlphaType              at;
    skcms_Matrix3x3          gamut;
    skcms_TransferFunction   tf;

    if (!parse_flag(FLAGS_backend, "backend", kBackends         , &backend) ||
        !parse_flag(FLAGS_ct     , "ct"     , kColorTypes       , &ct)      ||
        !parse_flag(FLAGS_at     , "at"     , kAlphaTypes       , &at)      ||
        !parse_flag(FLAGS_gamut  , "gamut"  , kGamuts           , &gamut)   ||
        !parse_flag(FLAGS_tf     , "tf"     , kTransferFunctions, &tf)) {
        return 1;
    }

    sk_sp<SkColorSpace> cs = FLAGS_legacy ? nullptr
                                          : SkColorSpace::MakeRGB(tf,gamut);
    const SkImageInfo unsized_info = SkImageInfo::Make(0,0, ct,at,cs);

    AutoreleasePool pool;
    for (auto source : sources) {
        const auto start = std::chrono::steady_clock::now();
        fprintf(stdout, "%50s", source.name.c_str());
        fflush(stdout);

        const SkImageInfo info = unsized_info.makeDimensions(source.size);

        auto draw = [&source](SkCanvas* canvas) {
            Result result = source.draw(canvas);
            switch (result.status) {
                case Result::Ok:   break;
                case Result::Skip: return false;
                case Result::Fail:
                    SK_ABORT(result.failure.c_str());
            }
            return true;
        };

        GrContextOptions options = baseOptions;
        source.tweak(&options);
        GrContextFactory factory(options);  // N.B. factory must outlive image

        sk_sp<SkImage> image;
        sk_sp<SkData>  blob;
        const char*    ext = ".png";
        switch (backend) {
            case kCPU_Backend:
                image = draw_with_cpu(draw, info);
                break;
            case kSKP_Backend:
                blob = draw_as_skp(draw, info);
                ext  = ".skp";
                break;
            case kPDF_Backend:
                blob = draw_as_pdf(draw, info, source.name);
                ext  = ".pdf";
                break;
            default:
                image = draw_with_gpu(draw, info, (GrContextFactory::ContextType)backend, &factory);
                break;
        }

        if (!image && !blob) {
            fprintf(stdout, "\tskipped\n");
            continue;
        }

        // We read back a bitmap even when --quick is set and we won't use it,
        // to keep us honest about deferred work, flushing pipelines, etc.
        SkBitmap bitmap;
        if (image && !image->asLegacyBitmap(&bitmap)) {
            SK_ABORT("SkImage::asLegacyBitmap() failed.");
        }

        SkString md5;
        if (!FLAGS_quick) {
            HashAndEncode hashAndEncode{bitmap};
            {
                SkMD5 hash;
                if (image) {
                    hashAndEncode.write(&hash);
                } else {
                    hash.write(blob->data(), blob->size());
                }

                SkMD5::Digest digest = hash.finish();
                for (int i = 0; i < 16; i++) {
                    md5.appendf("%02x", digest.data[i]);
                }
            }

            if (!FLAGS_writePath.isEmpty()) {
                sk_mkdir(FLAGS_writePath[0]);
                SkString path = SkStringPrintf("%s/%s%s",
                                               FLAGS_writePath[0], source.name.c_str(), ext);

                if (image) {
                    if (!hashAndEncode.writePngTo(path.c_str(), md5.c_str(),
                                                  FLAGS_key, FLAGS_properties)) {
                        SK_ABORT("Could not write .png.");
                    }
                } else {
                    SkFILEWStream file(path.c_str());
                    file.write(blob->data(), blob->size());
                }
            }
        }

        const auto elapsed = std::chrono::steady_clock::now() - start;
        fprintf(stdout, "\t%s\t%7dms\n",
                md5.c_str(),
                (int)std::chrono::duration_cast<std::chrono::milliseconds>(elapsed).count());
        pool.drain();
    }

    if (!FLAGS_writeShaders.isEmpty()) {
        sk_mkdir(FLAGS_writeShaders[0]);
        GrBackendApi api =
                GrContextFactory::ContextTypeBackend((GrContextFactory::ContextType)backend);
        memoryCache.writeShadersToDisk(FLAGS_writeShaders[0], api);

    }

    return 0;
}
