// 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);
    const FakeMCBlob* prior = nullptr;
    for (auto c : test) {
        c->execute(&fake);
        c->execute(&real, prior);
        prior = c->state();
    }

    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));

    //---------------------------------------------------------------------------------------------
    FakeStateTracker s;
    sk_sp<FakeMCBlob> state = s.snapState();

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

    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));

    //---------------------------------------------------------------------------------------------
    FakeStateTracker s;
    sk_sp<FakeMCBlob> state = s.snapState();

    SkIRect r{0, 0, 100, 100};
    test->push_back(new RectCmd(ID(0), {}, r.makeOffset(8, 8),   FakePaint(SK_ColorRED),   state));
    test->push_back(new RectCmd(ID(1), {}, r.makeOffset(48, 48), FakePaint(SK_ColorGREEN), state));
    test->push_back(new RectCmd(ID(2), {}, r.makeOffset(98, 98), FakePaint(SK_ColorBLUE),  state));
    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));

    //---------------------------------------------------------------------------------------------
    FakeStateTracker s;
    sk_sp<FakeMCBlob> state = s.snapState();

    SkIRect r{0, 0, 100, 100};
    test->push_back(new RectCmd(ID(0), {}, r.makeOffset(8, 8),   FakePaint(SK_ColorRED),  state));
    test->push_back(new RectCmd(ID(1), {}, r.makeOffset(48, 48), FakePaint(0x8000FF00),   state));
    test->push_back(new RectCmd(ID(2), {}, r.makeOffset(98, 98), FakePaint(SK_ColorBLUE), state));
    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));

    //---------------------------------------------------------------------------------------------
    FakeStateTracker s;
    sk_sp<FakeMCBlob> state = s.snapState();

    SkIRect r{0, 0, 100, 100};
    test->push_back(new RectCmd(ID(0), {}, r.makeOffset(8, 8),   FakePaint(0x80FF0000), state));
    test->push_back(new RectCmd(ID(1), {}, r.makeOffset(48, 48), FakePaint(0x8000FF00), state));
    test->push_back(new RectCmd(ID(2), {}, r.makeOffset(98, 98), FakePaint(0x800000FF), state));
    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));

    //---------------------------------------------------------------------------------------------
    FakeStateTracker s;
    sk_sp<FakeMCBlob> state = s.snapState();

    FakePaint p;

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

    //---------------------------------------------------------------------------------------------
    FakeStateTracker s;
    s.clipRect(SkIRect::MakeXYWH(28, 28, 40, 40));

    sk_sp<FakeMCBlob> state = s.snapState();

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

    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(5));
    expectedOrder->push_back(ID(4));
    expectedOrder->push_back(ID(1));
    expectedOrder->push_back(ID(0));

    expectedOrder->push_back(ID(3));
    expectedOrder->push_back(ID(2));

    //---------------------------------------------------------------------------------------------
    FakeStateTracker s;
    s.clipRect(SkIRect::MakeXYWH(85, 0, 86, 256));  // select the middle third in x

    sk_sp<FakeMCBlob> state = s.snapState();

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

    s.push();
    s.clipRect(SkIRect::MakeXYWH(0, 85, 256, 86));  // intersect w/ the middle third in y
    state = s.snapState();

    test->push_back(new RectCmd(ID(2), {}, r.makeOffset(98, 98),   FakePaint(SK_ColorBLUE),    state));
    test->push_back(new RectCmd(ID(3), {}, r.makeOffset(148, 148), FakePaint(SK_ColorCYAN),    state));

    s.pop();
    state = s.snapState();

    test->push_back(new RectCmd(ID(4), {}, r.makeOffset(148, 8),   FakePaint(SK_ColorMAGENTA), state));
    test->push_back(new RectCmd(ID(5), {}, r.makeOffset(8, 148),   FakePaint(SK_ColorYELLOW),  state));

    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;
}
