/*
 * 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 "include/core/SkMatrix.h"
#include "include/core/SkRect.h"
#include "include/core/SkTypes.h"
#include "src/gpu/ganesh/geometry/GrQuad.h"
#include "src/gpu/ganesh/geometry/GrQuadBuffer.h"
#include "tests/Test.h"

#include <utility>
#include <vector>

#define ASSERT(cond) REPORTER_ASSERT(r, cond)
#define ASSERTF(cond, ...) REPORTER_ASSERT(r, cond, __VA_ARGS__)
#define TEST(name) DEF_TEST(GrQuadBuffer##name, r)

struct TestData {
    int fItem1;
    float fItem2;
};

static void assert_quad_eq(skiatest::Reporter* r, const GrQuad& expected, const GrQuad& actual) {
    ASSERTF(expected.quadType() == actual.quadType(), "Expected type %d, got %d",
            (int) expected.quadType(), (int) actual.quadType());
    for (int i = 0; i < 4; ++i) {
        ASSERTF(expected.x(i) == actual.x(i), "Expected x(%d) = %f, got %f",
                i, expected.x(i), actual.x(i));
        ASSERTF(expected.y(i) == actual.y(i), "Expected y(%d) = %f, got %f",
                i, expected.y(i), actual.y(i));
        ASSERTF(expected.w(i) == actual.w(i), "Expected w(%d) = %f, got %f",
                i, expected.w(i), actual.w(i));
    }
}

static void assert_metadata_eq(skiatest::Reporter* r, const TestData& expected,
                               const TestData& actual) {
    ASSERTF(expected.fItem1 == actual.fItem1 && expected.fItem2 == actual.fItem2,
            "Expected { %d, %f } for metadata, got: { %d %f }",
            expected.fItem1, expected.fItem2, actual.fItem1, actual.fItem2);
}

static std::vector<GrQuad> generate_quads(float seed, int cnt, const GrQuad::Type types[]) {
    // For convenience use matrix to derive each quad type, rely on different seed values to
    // differentiate between quads of the same type
    SkMatrix rotate;
    rotate.setRotate(45.f);
    SkMatrix skew;
    skew.setSkew(0.5f, 0.5f);
    SkMatrix perspective;
    perspective.setPerspX(0.01f);
    perspective.setPerspY(0.001f);

    std::vector<GrQuad> quads;
    SkRect rect = SkRect::MakeXYWH(seed, 2.f * seed, 2.f * seed, seed);
    for (int i = 0; i < cnt; ++i) {
        GrQuad quad;
        switch(types[i]) {
            case GrQuad::Type::kAxisAligned:
                quad = GrQuad(rect);
                break;
            case GrQuad::Type::kRectilinear:
                quad = GrQuad::MakeFromRect(rect, rotate);
                break;
            case GrQuad::Type::kGeneral:
                quad = GrQuad::MakeFromRect(rect, skew);
                break;
            default:
                SkASSERT(types[i] == GrQuad::Type::kPerspective);
                quad = GrQuad::MakeFromRect(rect, perspective);
                break;
        }

        SkASSERT(quad.quadType() == types[i]);
        quads.push_back(quad);
    }
    return quads;
}

TEST(Append) {
    // Generate test data, which includes all quad types out of enum-order and duplicates
    static const int kQuadCount = 6;
    static const GrQuad::Type kDeviceTypes[] = {
        GrQuad::Type::kAxisAligned, GrQuad::Type::kRectilinear, GrQuad::Type::kGeneral,
        GrQuad::Type::kPerspective, GrQuad::Type::kRectilinear, GrQuad::Type::kAxisAligned
    };
    // Odd indexed quads will be ignored and not stored in the buffer
    static const GrQuad::Type kLocalTypes[] = {
        GrQuad::Type::kGeneral, GrQuad::Type::kGeneral, GrQuad::Type::kRectilinear,
        GrQuad::Type::kRectilinear, GrQuad::Type::kAxisAligned, GrQuad::Type::kAxisAligned
    };
    static_assert(std::size(kDeviceTypes) == kQuadCount, "device quad count");
    static_assert(std::size(kLocalTypes) == kQuadCount, "local quad count");

    std::vector<GrQuad> expectedDeviceQuads = generate_quads(1.f, kQuadCount, kDeviceTypes);
    std::vector<GrQuad> expectedLocalQuads = generate_quads(2.f, kQuadCount, kLocalTypes);

    // Fill in the buffer with the device quads, and a local quad if the index is even
    GrQuadBuffer<TestData> buffer;
    for (int i = 0; i < kQuadCount; ++i) {
        buffer.append(expectedDeviceQuads[i],                          // device quad
                      { 2 * i, 3.f * i },                              // metadata
                      i % 2 == 0 ? &expectedLocalQuads[i] : nullptr);  // optional local quad
    }

    // Confirm the state of the buffer
    ASSERT(kQuadCount == buffer.count());
    ASSERT(GrQuad::Type::kPerspective == buffer.deviceQuadType());
    ASSERT(GrQuad::Type::kGeneral == buffer.localQuadType());

    int i = 0;
    auto iter = buffer.iterator();
    while(iter.next()) {
        // Each entry always has the device quad
        assert_quad_eq(r, expectedDeviceQuads[i], *iter.deviceQuad());
        assert_metadata_eq(r, {2 * i, 3.f * i}, iter.metadata());

        if (i % 2 == 0) {
            // Confirm local quads included on even entries
            ASSERT(iter.isLocalValid());
            assert_quad_eq(r, expectedLocalQuads[i], *iter.localQuad());
        } else {
            // Should not have locals
            ASSERT(!iter.isLocalValid());
            ASSERT(!iter.localQuad());
        }

        i++;
    }
    ASSERTF(i == kQuadCount, "Expected %d iterations, got: %d", kQuadCount, i);
}

TEST(Concat) {
    static const int kQuadCount = 2;
    static const GrQuad::Type kTypesA[] = { GrQuad::Type::kAxisAligned, GrQuad::Type::kRectilinear };
    static const GrQuad::Type kTypesB[] = { GrQuad::Type::kGeneral, GrQuad::Type::kPerspective };
    static_assert(std::size(kTypesA) == kQuadCount, "quadsA count");
    static_assert(std::size(kTypesB) == kQuadCount, "quadsB count");

    std::vector<GrQuad> quadsA = generate_quads(1.f, kQuadCount, kTypesA);
    std::vector<GrQuad> quadsB = generate_quads(2.f, kQuadCount, kTypesB);
    // Make two buffers, the first uses 'quadsA' for device quads and 'quadsB' for local quads
    // on even indices. The second uses 'quadsB' for device quads and 'quadsA' for local quads
    // on odd indices.
    GrQuadBuffer<TestData> buffer1;
    GrQuadBuffer<TestData> buffer2;
    for (int i = 0; i < kQuadCount; ++i) {
        buffer1.append(quadsA[i], {i, 2.f * i}, i % 2 == 0 ? &quadsB[i] : nullptr);
        buffer2.append(quadsB[i], {2 * i, 0.5f * i}, i % 2 == 0 ? nullptr : &quadsA[i]);
    }

    ASSERT(kQuadCount == buffer1.count());
    ASSERT(kQuadCount == buffer2.count());

    // Perform the concatenation and then confirm the new state of buffer1
    buffer1.concat(buffer2);

    ASSERT(2 * kQuadCount == buffer1.count());
    int i = 0;
    auto iter = buffer1.iterator();
    while(iter.next()) {
        if (i < kQuadCount) {
            // First half should match original buffer1
            assert_quad_eq(r, quadsA[i], *iter.deviceQuad());
            assert_metadata_eq(r, {i, 2.f * i}, iter.metadata());
            if (i % 2 == 0) {
                ASSERT(iter.isLocalValid());
                assert_quad_eq(r, quadsB[i], *iter.localQuad());
            } else {
                ASSERT(!iter.isLocalValid());
                ASSERT(!iter.localQuad());
            }

        } else {
            // Second half should match buffer2
            int j = i - kQuadCount;
            assert_quad_eq(r, quadsB[j], *iter.deviceQuad());
            assert_metadata_eq(r, {2 * j, 0.5f * j}, iter.metadata());
            if (j % 2 == 0) {
                ASSERT(!iter.isLocalValid());
                ASSERT(!iter.localQuad());
            } else {
                ASSERT(iter.isLocalValid());
                assert_quad_eq(r, quadsA[j], *iter.localQuad());
            }
        }

        i++;
    }
    ASSERTF(i == 2 * kQuadCount, "Expected %d iterations, got: %d",2 * kQuadCount, i);
}

TEST(Metadata) {
    static const int kQuadCount = 3;

    // This test doesn't really care about the quad coordinates (except that they aren't modified
    // when mutating the metadata)
    GrQuad quad(SkRect::MakeLTRB(1.f, 2.f, 3.f, 4.f));

    GrQuadBuffer<TestData> buffer;
    for (int i = 0; i < kQuadCount; ++i) {
        buffer.append(quad, {i, 2.f * i}, i % 2 == 0 ? &quad : nullptr);
    }

    // Iterate once using the metadata iterator, confirm the test data and rewrite
    int i = 0;
    auto meta = buffer.metadata();
    while(meta.next()) {
        // Confirm initial state
        assert_metadata_eq(r, {i, 2.f * i}, *meta);
        // Rewrite
        *meta = {2 * i, 0.5f * i};
        i++;
    }
    ASSERTF(i == kQuadCount, "Expected %d iterations, got: %d", kQuadCount, i);

    // Now that all metadata has been touched, read with regular iterator and confirm updated state
    // and that no quad coordinates have been changed.
    i = 0;
    auto iter = buffer.iterator();
    while(iter.next()) {
        // New metadata
        assert_metadata_eq(r, {2 * i, 0.5f * i}, iter.metadata());

        // Quad coordinates are unchanged
        assert_quad_eq(r, quad, *iter.deviceQuad());
        if (i % 2 == 0) {
            ASSERT(iter.isLocalValid());
            assert_quad_eq(r, quad, *iter.localQuad());
        } else {
            ASSERT(!iter.isLocalValid());
            ASSERT(!iter.localQuad());
        }
        i++;
    }
    ASSERTF(i == kQuadCount, "Expected %d iterations, got: %d", kQuadCount, i);
}
