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

#include "experimental/ngatoy/Cmds.h"
#include "experimental/ngatoy/Fake.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkGraphics.h"
#include "include/gpu/GrDirectContext.h"
#include "src/core/SkOSFile.h"
#include "src/gpu/GrCaps.h"
#include "src/gpu/GrDirectContextPriv.h"
#include "src/utils/SkOSPath.h"
#include "tools/ToolUtils.h"
#include "tools/flags/CommandLineFlags.h"
#include "tools/gpu/GrContextFactory.h"

#include <algorithm>

/*
 * Questions this is trying to answer:
 *   How to handle saveLayers (in w/ everything or separate)
 *   How to handle blurs & other off screen draws
 *   How to handle clipping
 *   How does sorting stack up against buckets
 *   How does creating batches interact w/ the sorting
 *   How does batching work w/ text
 *   How does text (esp. atlasing) work at all
 *   Batching quality vs. existing
 *   Memory churn/overhead vs existing (esp. wrt batching)
 *   gpu vs cpu boundedness
 *
 * Futher Questions:
 *   How can we collect uniforms & not store the fps -- seems complicated
 *   Do all the blend modes (esp. advanced work front-to-back)?
 *   NGA perf vs. OGA perf
 *   Can we prepare any of the saveLayers or off-screen draw render passes in parallel?
 *
 * Small potatoes:
 *   Incorporate CTM into the simulator
 */

/*
 * How does this all work:
 *
 * Each test is specified by a set of RectCmds (which have a unique ID and carry their material
 * and MC state info) along with the order they are expected to be drawn in with the NGA.
 *
 * To generate an expected image, the RectCmds are replayed into an SkCanvas in the order
 * provided.
 *
 * For the actual (NGA) image, the RectCmds are replayed into a FakeCanvas - preserving the
 * unique ID of the RectCmd. The FakeCanvas creates new RectCmd objects, sorts them using
 * the SortKey and then performs a kludgey z-buffered rasterization. The FakeCanvas also
 * preserves the RectCmd order it ultimately used for its rendering and this can be compared
 * with the expected order from the test.
 *
 * The use of the RectCmds to create the tests is a mere convenience to avoid creating a
 * separate representation of the desired draws.
 *
 ***************************
 * Here are some of the simplifying assumptions of this simulation (and their justification):
 *
 * Only SkIRects are used for draws and clips - since MSAA should be taking care of AA for us in
 * the NGA we don't really need SkRects. This also greatly simplifies the z-buffered rasterization.
 *
 **************************
 * Areas for improvement:
 *   We should add strokes since there are two distinct drawing methods in the NGA (fill v. stroke)
 */

using sk_gpu_test::GrContextFactory;

static DEFINE_string2(writePath, w, "", "If set, write bitmaps here as .pngs.");

static void exitf(const char* format, ...) {
    va_list args;
    va_start(args, format);
    vfprintf(stderr, format, args);
    va_end(args);

    exit(1);
}

static void save_files(int testID, const SkBitmap& expected, const SkBitmap& actual) {
    if (FLAGS_writePath.isEmpty()) {
        return;
    }

    const char* dir = FLAGS_writePath[0];

    SkString path = SkOSPath::Join(dir, "expected");
    path.appendU32(testID);
    path.append(".png");

    if (!sk_mkdir(dir)) {
        exitf("failed to create directory for png \"%s\"", path.c_str());
    }
    if (!ToolUtils::EncodeImageToFile(path.c_str(), expected, SkEncodedImageFormat::kPNG, 100)) {
        exitf("failed to save png to \"%s\"", path.c_str());
    }

    path = SkOSPath::Join(dir, "actual");
    path.appendU32(testID);
    path.append(".png");

    if (!ToolUtils::EncodeImageToFile(path.c_str(), actual, SkEncodedImageFormat::kPNG, 100)) {
        exitf("failed to save png to \"%s\"", path.c_str());
    }
}

// Exercise basic SortKey behavior
static void key_test() {
    SortKey k;
    SkASSERT(!k.transparent());
    SkASSERT(k.clipID() == 0);
    SkASSERT(k.depth() == 0);
    SkASSERT(k.material() == 0);
//    k.dump();

    SortKey k1(false, 4, 1, 3);
    SkASSERT(!k1.transparent());
    SkASSERT(k1.clipID() == 4);
    SkASSERT(k1.depth() == 1);
    SkASSERT(k1.material() == 3);
//    k1.dump();

    SortKey k2(true, 7, 2, 1);
    SkASSERT(k2.transparent());
    SkASSERT(k2.clipID() == 7);
    SkASSERT(k2.depth() == 2);
    SkASSERT(k2.material() == 1);
//    k2.dump();
}

static void check_state(FakeMCBlob* actualState,
                        SkIPoint expectedCTM,
                        const std::vector<SkIRect>& expectedClips) {
    SkASSERT(actualState->ctm() == expectedCTM);

    int i = 0;
    auto states = actualState->mcStates();
    for (auto& s : states) {
        for (auto r : s.rects()) {
            SkAssertResult(i < (int) expectedClips.size());
            SkAssertResult(r == expectedClips[i]);
            i++;
        }
    }
}

// Exercise the FakeMCBlob object
static void mcstack_test() {
    const SkIRect r { 0, 0, 10, 10 };
    const SkIPoint s1Trans { 10, 10 };
    const SkIPoint s2TransA { -5, -2 };
    const SkIPoint s2TransB { -3, -1 };

    const std::vector<SkIRect> expectedS0Clips;
    const std::vector<SkIRect> expectedS1Clips {
        r.makeOffset(s1Trans)
    };
    const std::vector<SkIRect> expectedS2aClips {
        r.makeOffset(s1Trans),
        r.makeOffset(s2TransA)
    };
    const std::vector<SkIRect> expectedS2bClips {
        r.makeOffset(s1Trans),
        r.makeOffset(s2TransA),
        r.makeOffset(s2TransA + s2TransB)
    };

    //----------------
    FakeStateTracker s;

    auto state0 = s.snapState();
    // The initial state should have no translation & no clip
    check_state(state0.get(), { 0, 0 }, expectedS0Clips);

    //----------------
    s.push();
    s.translate(s1Trans);
    s.clipRect(r);

    auto state1 = s.snapState();
    check_state(state1.get(), s1Trans, expectedS1Clips);

    //----------------
    s.push();
    s.translate(s2TransA);
    s.clipRect(r);

    auto state2a = s.snapState();
    check_state(state2a.get(), s1Trans + s2TransA, expectedS2aClips);

    s.translate(s2TransB);
    s.clipRect(r);

    auto state2b = s.snapState();
    check_state(state2b.get(), s1Trans + s2TransA + s2TransB, expectedS2bClips);
    SkASSERT(state2a != state2b);

    //----------------
    s.pop();
    auto state3 = s.snapState();
    check_state(state3.get(), s1Trans, expectedS1Clips);
    SkASSERT(state1 == state3);

    //----------------
    s.pop();
    auto state4 = s.snapState();
    check_state(state4.get(), { 0, 0 }, expectedS0Clips);
    SkASSERT(state0 == state4);
}

static void check_order(const std::vector<ID>& actualOrder,
                        const std::vector<ID>& expectedOrder) {
    if (expectedOrder.size() != actualOrder.size()) {
        exitf("Op count mismatch. Expected %d - got %d\n",
              expectedOrder.size(),
              actualOrder.size());
    }

    if (expectedOrder != actualOrder) {
        SkDebugf("order mismatch:\n");
        SkDebugf("E %d: ", expectedOrder.size());
        for (auto t : expectedOrder) {
            SkDebugf("%d", t.toInt());
        }
        SkDebugf("\n");

        SkDebugf("A %d: ", actualOrder.size());
        for (auto t : actualOrder) {
            SkDebugf("%d", t.toInt());
        }
        SkDebugf("\n");
    }
}

typedef int (*PFTest)(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder);

static void sort_test(PFTest testcase) {
    std::vector<const Cmd*> test;
    std::vector<ID> expectedOrder;
    int testID = testcase(&test, &expectedOrder);


    SkBitmap expectedBM;
    expectedBM.allocPixels(SkImageInfo::MakeN32Premul(256, 256));
    expectedBM.eraseColor(SK_ColorBLACK);
    SkCanvas real(expectedBM);

    SkBitmap actualBM;
    actualBM.allocPixels(SkImageInfo::MakeN32Premul(256, 256));
    actualBM.eraseColor(SK_ColorBLACK);

    FakeCanvas fake(actualBM);
    for (auto c : test) {
        c->execute(&fake);
        c->execute(&real);
    }

    fake.finalize();

    std::vector<ID> actualOrder = fake.getOrder();
    check_order(actualOrder, expectedOrder);

    save_files(testID, expectedBM, actualBM);
}

// Simple test - green rect should appear atop the red rect
static int test1(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder) {
    // front-to-back order bc all opaque
    expectedOrder->push_back(ID(1));
    expectedOrder->push_back(ID(0));

    //---------------------------------------------------------------------------------------------
    test->push_back(new SaveCmd());

    SkIRect r{0, 0, 100, 100};
    test->push_back(new RectCmd(ID(0), {}, r.makeOffset(8, 8),   FakePaint(SK_ColorRED),   nullptr));
    test->push_back(new RectCmd(ID(1), {}, r.makeOffset(48, 48), FakePaint(SK_ColorGREEN), nullptr));

    test->push_back(new RestoreCmd());
    return 1;
}

// Simple test - blue rect atop green rect atop red rect
static int test2(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder) {
    // front-to-back order bc all opaque
    expectedOrder->push_back(ID(2));
    expectedOrder->push_back(ID(1));
    expectedOrder->push_back(ID(0));

    //---------------------------------------------------------------------------------------------
    test->push_back(new SaveCmd());

    SkIRect r{0, 0, 100, 100};
    test->push_back(new RectCmd(ID(0), {}, r.makeOffset(8, 8),   FakePaint(SK_ColorRED),   nullptr));
    test->push_back(new RectCmd(ID(1), {}, r.makeOffset(48, 48), FakePaint(SK_ColorGREEN), nullptr));
    test->push_back(new RectCmd(ID(2), {}, r.makeOffset(98, 98), FakePaint(SK_ColorBLUE),  nullptr));

    test->push_back(new RestoreCmd());
    return 2;
}

// Transparency test - opaque blue rect atop transparent green rect atop opaque red rect
static int test3(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder) {
    // opaque draws are first and are front-to-back. Transparent draw is last.
    expectedOrder->push_back(ID(2));
    expectedOrder->push_back(ID(0));
    expectedOrder->push_back(ID(1));

    //---------------------------------------------------------------------------------------------
    test->push_back(new SaveCmd());

    SkIRect r{0, 0, 100, 100};
    test->push_back(new RectCmd(ID(0), {}, r.makeOffset(8, 8),   FakePaint(SK_ColorRED),  nullptr));
    test->push_back(new RectCmd(ID(1), {}, r.makeOffset(48, 48), FakePaint(0x8000FF00),   nullptr));
    test->push_back(new RectCmd(ID(2), {}, r.makeOffset(98, 98), FakePaint(SK_ColorBLUE), nullptr));

    test->push_back(new RestoreCmd());
    return 3;
}

// Multi-transparency test - transparent blue rect atop transparent green rect atop
// transparent red rect
static int test4(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder) {
    // All in back-to-front order bc they're all transparent
    expectedOrder->push_back(ID(0));
    expectedOrder->push_back(ID(1));
    expectedOrder->push_back(ID(2));

    //---------------------------------------------------------------------------------------------
    test->push_back(new SaveCmd());

    SkIRect r{0, 0, 100, 100};
    test->push_back(new RectCmd(ID(0), {}, r.makeOffset(8, 8),   FakePaint(0x80FF0000), nullptr));
    test->push_back(new RectCmd(ID(1), {}, r.makeOffset(48, 48), FakePaint(0x8000FF00), nullptr));
    test->push_back(new RectCmd(ID(2), {}, r.makeOffset(98, 98), FakePaint(0x800000FF), nullptr));

    test->push_back(new RestoreCmd());
    return 4;
}

// Multiple opaque materials test
// All opaque:
//   normal1, linear1, radial1, normal2, linear2, radial2
// Which gets sorted to:
//   normal2, normal1, linear2, linear1, radial2, radial1
// So, front to back w/in each material type.
static int test5(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder) {
    // Note: This pushes sorting by material above sorting by Z. Thus we'll get less front to
    // back benefit.
    expectedOrder->push_back(ID(3));
    expectedOrder->push_back(ID(0));
    expectedOrder->push_back(ID(4));
    expectedOrder->push_back(ID(1));
    expectedOrder->push_back(ID(5));
    expectedOrder->push_back(ID(2));

    //---------------------------------------------------------------------------------------------
    test->push_back(new SaveCmd());

    FakePaint p;

    SkIRect r{0, 0, 100, 100};
    test->push_back(new RectCmd(ID(0), {}, r.makeOffset(8, 8),     FakePaint(SK_ColorRED),  nullptr));
    p.setLinear(SK_ColorGREEN,   SK_ColorWHITE);
    test->push_back(new RectCmd(ID(1), {}, r.makeOffset(48, 48),   p,                       nullptr));
    p.setRadial(SK_ColorBLUE,    SK_ColorBLACK);
    test->push_back(new RectCmd(ID(2), {}, r.makeOffset(98, 98),   p,                       nullptr));
    test->push_back(new RectCmd(ID(3), {}, r.makeOffset(148, 148), FakePaint(SK_ColorCYAN), nullptr));
    p.setLinear(SK_ColorMAGENTA, SK_ColorWHITE);
    test->push_back(new RectCmd(ID(4), {}, r.makeOffset(148, 8),   p,                       nullptr));
    p.setRadial(SK_ColorYELLOW,  SK_ColorBLACK);
    test->push_back(new RectCmd(ID(5), {}, r.makeOffset(8, 148),   p,                       nullptr));

    test->push_back(new RestoreCmd());
    return 5;
}

// simple clipping test - 1 clip w/ two opaque rects
static int test6(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder) {
    // The expected is front to back after the clip
    expectedOrder->push_back(ID(2));
    expectedOrder->push_back(ID(1));

    //---------------------------------------------------------------------------------------------
    test->push_back(new SaveCmd());

    test->push_back(new ClipCmd(ID(0), {}, SkIRect::MakeXYWH(28, 28, 40, 40)));

    SkIRect r{0, 0, 100, 100};
    test->push_back(new RectCmd(ID(1), {}, r.makeOffset(8, 8),   FakePaint(SK_ColorRED),   nullptr));
    test->push_back(new RectCmd(ID(2), {}, r.makeOffset(48, 48), FakePaint(SK_ColorGREEN), nullptr));

    test->push_back(new RestoreCmd());
    return 6;
}

// more complicated clipping w/ opaque draws -> should reorder
static int test7(std::vector<const Cmd*>* test, std::vector<ID>* expectedOrder) {
    // The expected is front to back modulated by the two clip states
    expectedOrder->push_back(ID(7));
    expectedOrder->push_back(ID(6));
    expectedOrder->push_back(ID(2));
    expectedOrder->push_back(ID(1));

    expectedOrder->push_back(ID(5));
    expectedOrder->push_back(ID(4));

    //---------------------------------------------------------------------------------------------
    test->push_back(new SaveCmd());
    // select the middle third in x
    test->push_back(new ClipCmd(ID(0), {}, SkIRect::MakeXYWH(85, 0, 86, 256)));

    SkIRect r{0, 0, 100, 100};
    test->push_back(new RectCmd(ID(1), {}, r.makeOffset(8, 8),     FakePaint(SK_ColorRED),     nullptr));
    test->push_back(new RectCmd(ID(2), {}, r.makeOffset(48, 48),   FakePaint(SK_ColorGREEN),   nullptr));

    test->push_back(new SaveCmd());
    // intersect w/ the middle third in y
    test->push_back(new ClipCmd(ID(3), {}, SkIRect::MakeXYWH(0, 85, 256, 86)));

    test->push_back(new RectCmd(ID(4), {}, r.makeOffset(98, 98),   FakePaint(SK_ColorBLUE),    nullptr));
    test->push_back(new RectCmd(ID(5), {}, r.makeOffset(148, 148), FakePaint(SK_ColorCYAN),    nullptr));

    test->push_back(new RestoreCmd());

    test->push_back(new RectCmd(ID(6), {}, r.makeOffset(148, 8),   FakePaint(SK_ColorMAGENTA), nullptr));
    test->push_back(new RectCmd(ID(7), {}, r.makeOffset(8, 148),   FakePaint(SK_ColorYELLOW),  nullptr));

    test->push_back(new RestoreCmd());
    return 7;
}

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

    SkGraphics::Init();

    key_test();
    mcstack_test();
    sort_test(test1);
    sort_test(test2);
    sort_test(test3);
    sort_test(test4);
    sort_test(test5);
    sort_test(test6);
    sort_test(test7);

    return 0;
}
