/*
 * Copyright 2026 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/SkPathBuilder.h"
#include "src/gpu/graphite/sparse_strips/Flatten.h"
#include "src/gpu/graphite/sparse_strips/Polyline.h"
#include "tests/Test.h"

#include <cmath>
#include <iterator>

namespace skgpu::graphite {

DEF_TEST(SparseStrips_Polyline, reporter) {
    // Append Deduplications
    {
        Polyline polyline;
        REPORTER_ASSERT(reporter, polyline.empty());
        REPORTER_ASSERT(reporter, polyline.count() == 0);

        polyline.appendPoint({0.0f, 0.0f});
        REPORTER_ASSERT(reporter, polyline.count() == 1);

        polyline.appendPoint({0.0f, 0.0f});
        REPORTER_ASSERT(reporter, polyline.count() == 1);

        polyline.appendPoint({1.0f, 1.0f});
        REPORTER_ASSERT(reporter, polyline.count() == 2);

        polyline.appendSentinel();
        REPORTER_ASSERT(reporter, polyline.count() == 3);
        REPORTER_ASSERT(reporter, std::isnan(polyline.points().back().fX));
        REPORTER_ASSERT(reporter, std::isnan(polyline.points().back().fY));

        polyline.appendSentinel();
        REPORTER_ASSERT(reporter, polyline.count() == 3);

        polyline.reset();
        REPORTER_ASSERT(reporter, polyline.empty());
        polyline.appendSentinel();
        REPORTER_ASSERT(reporter, polyline.empty());
    }

    // Iterator
    {
        Polyline polyline;

        polyline.appendPoint({0.0f, 0.0f});
        polyline.appendPoint({1.0f, 0.0f});
        polyline.appendPoint({1.0f, 1.0f});
        polyline.appendSentinel();

        polyline.appendPoint({5.0f, 5.0f});
        polyline.appendPoint({6.0f, 6.0f});
        polyline.appendSentinel();

        polyline.appendPoint({10.0f, 10.0f});
        polyline.appendSentinel();

        int expectedIndices[] = {0, 1, 4};
        int count = 0;

        for (auto it = polyline.begin(); it != polyline.end(); ++it) {
            int idx = (*it).second;
            REPORTER_ASSERT(reporter, count < 3);
            REPORTER_ASSERT(reporter, idx == expectedIndices[count]);
            count++;
        }

        REPORTER_ASSERT(reporter, count == 3);
    }

    // Malformed inputs
    {
        static constexpr float kNaN = SK_ScalarNaN;
        static constexpr SkPoint kPathologicalPts[] = {
            {kNaN, kNaN},
            {kNaN, kNaN},
            {kNaN, kNaN},
            {kNaN, kNaN},
            {kNaN, kNaN},
            {0.0f, 0.0f},
            {kNaN, kNaN},
            {kNaN, kNaN},
            {1.0f, 1.0f},
            {2.0f, 2.0f},
            {kNaN, kNaN},
            {kNaN, kNaN},
            {kNaN, kNaN},
            {kNaN, kNaN},
            {kNaN, kNaN},
            {kNaN, kNaN},
            {3.0f, 3.0f},
            {kNaN, kNaN},
            {4.0f, 4.0f},
            {5.0f, 5.0f},
            {6.0f, 6.0f},
            {kNaN, kNaN},
            {7.0f, 7.0f},
            {kNaN, kNaN},
            {kNaN, kNaN},
            {kNaN, kNaN},
            {kNaN, kNaN}
        };

        int count = std::size(kPathologicalPts);
        Polyline::LineIterator it(kPathologicalPts, 0, count);
        Polyline::LineIterator end(kPathologicalPts, count, count);

        REPORTER_ASSERT(reporter, it != end);
        REPORTER_ASSERT(reporter, (*it).second == 8);
        ++it;

        REPORTER_ASSERT(reporter, it != end);
        REPORTER_ASSERT(reporter, (*it).second == 18);
        ++it;

        REPORTER_ASSERT(reporter, it != end);
        REPORTER_ASSERT(reporter, (*it).second == 19);
        ++it;

        REPORTER_ASSERT(reporter, !(it != end));
    }

    // Empty/Null
    {
        Polyline polyline;

        auto it = polyline.begin();
        auto end = polyline.end();

        REPORTER_ASSERT(reporter, !(it != end));

        const SkPoint test[] = {{0.0f, 0.0f}};
        Polyline::LineIterator rawIt(test, 0, 0);
        Polyline::LineIterator rawEnd(test, 0, 0);

        REPORTER_ASSERT(reporter, !(rawIt != rawEnd));
    }

    // Single Point
    {
        const SkPoint pts[] = {{1.0f, 1.0f}};
        Polyline::LineIterator it(pts, 0, 1);
        Polyline::LineIterator end(pts, 1, 1);

        REPORTER_ASSERT(reporter, !(it != end));
    }
}

DEF_TEST(SparseStrips_Polyline_Integrated, reporter) {
    // Simple rect
    {
        SkPathBuilder builder;
        builder.addRect(SkRect::MakeXYWH(10, 10, 50, 50));
        SkPath path = builder.detach();

        Flatten flatten;
        Polyline polyline;

        flatten.processPaths<FlattenMode::kScalar>(path, SkMatrix::I(), 100.0f, 100.0f, &polyline);

        REPORTER_ASSERT(reporter, polyline.count() == 6);
        const auto& pts = polyline.points();
        REPORTER_ASSERT(reporter, pts[0] == SkPoint::Make(10, 10));
        REPORTER_ASSERT(reporter, pts[4] == SkPoint::Make(10, 10));
        REPORTER_ASSERT(reporter, std::isnan(pts[5].fX));

        int lineCount = 0;
        for (auto [line, index] : polyline) {
            lineCount++;
            REPORTER_ASSERT(reporter, !std::isnan(line.p0.fX) && !std::isnan(line.p1.fX));
        }
        REPORTER_ASSERT(reporter, lineCount == 4);
    }

    // NaN injection between sub-paths
    {
        SkPathBuilder builder;
        builder.moveTo(0, 0);
        builder.lineTo(10, 0);

        builder.moveTo(20, 20); // Triggers sentinel for previous open path
        builder.lineTo(30, 20);
        SkPath path = builder.detach();

        Flatten flatten;
        Polyline polyline;

        flatten.processPaths<FlattenMode::kScalar>(path, SkMatrix::I(), 100.0f, 100.0f, &polyline);

        REPORTER_ASSERT(reporter, polyline.count() == 8);

        const auto& pts = polyline.points();
        REPORTER_ASSERT(reporter, pts[1] == SkPoint::Make(10, 0));
        REPORTER_ASSERT(reporter, pts[2] == SkPoint::Make(0, 0));
        REPORTER_ASSERT(reporter, std::isnan(pts[3].fX));

        REPORTER_ASSERT(reporter, pts[4] == SkPoint::Make(20, 20));
        REPORTER_ASSERT(reporter, std::isnan(pts[7].fX));

        int lineCount = 0;
        for (auto [line, index] : polyline) {
            lineCount++;
            REPORTER_ASSERT(reporter, index != 2 && index != 3 && index != 6 && index != 7);
        }
        REPORTER_ASSERT(reporter, lineCount == 4);
    }

    // Deduplication
    {
        SkPathBuilder builder;
        builder.moveTo(0, 0);
        builder.lineTo(10, 10);
        builder.lineTo(10, 10);
        builder.lineTo(20, 0);
        builder.close();
        SkPath path = builder.detach();

        Flatten flatten;
        Polyline polyline;

        flatten.processPaths<FlattenMode::kScalar>(path, SkMatrix::I(), 100.0f, 100.0f, &polyline);

        REPORTER_ASSERT(reporter, polyline.count() == 5);
        const auto& pts = polyline.points();
        REPORTER_ASSERT(reporter, pts[1] == SkPoint::Make(10, 10));
        REPORTER_ASSERT(reporter, pts[2] == SkPoint::Make(20, 0));
    }

    // Simplification
    {
        SkPathBuilder builder;

        // Left of Viewport
        // Quad
        builder.moveTo(-10, 10);
        builder.quadTo(-20, 20, -30, 10);
        // Conic
        builder.moveTo(-10, 30);
        builder.conicTo(-20, 40, -30, 30, 0.5f);
        // Cubic
        builder.moveTo(-10, 50);
        builder.cubicTo(-20, 60, -30, 60, -40, 50);

        // Visually flat
        // Quad (Control point is collinear with start and end)
        builder.moveTo(10, 10);
        builder.quadTo(20, 10, 30, 10);
        // Conic (Control point is collinear)
        builder.moveTo(10, 30);
        builder.conicTo(20, 30, 30, 30, 0.5f);
        // Cubic (Both control points are collinear)
        builder.moveTo(10, 50);
        builder.cubicTo(20, 50, 30, 50, 40, 50);

        SkPath path = builder.detach();

        Flatten flatten;
        Polyline polyline;
        flatten.processPaths<FlattenMode::kScalar>(path, SkMatrix::I(), 100.0f, 100.0f, &polyline);
        // Expected per contour: Start Pt, Simplified End Pt, Implicit Close Pt, NaN.
        // 6 contours * 4 pts = 24 points total
        REPORTER_ASSERT(reporter, polyline.count() == 24);
        const auto& pts = polyline.points();

        // Left of Viewport Simplification
        REPORTER_ASSERT(reporter, pts[0] == SkPoint::Make(-10, 10));
        REPORTER_ASSERT(reporter, pts[1] == SkPoint::Make(-30, 10)); // Quad simplified
        REPORTER_ASSERT(reporter, pts[2] == SkPoint::Make(-10, 10)); // Close
        REPORTER_ASSERT(reporter, std::isnan(pts[3].fX));

        REPORTER_ASSERT(reporter, pts[4] == SkPoint::Make(-10, 30));
        REPORTER_ASSERT(reporter, pts[5] == SkPoint::Make(-30, 30)); // Conic simplified
        REPORTER_ASSERT(reporter, pts[6] == SkPoint::Make(-10, 30)); // Close
        REPORTER_ASSERT(reporter, std::isnan(pts[7].fX));

        REPORTER_ASSERT(reporter, pts[8] == SkPoint::Make(-10, 50));
        REPORTER_ASSERT(reporter, pts[9] == SkPoint::Make(-40, 50)); // Cubic simplified
        REPORTER_ASSERT(reporter, pts[10] == SkPoint::Make(-10, 50)); // Close
        REPORTER_ASSERT(reporter, std::isnan(pts[11].fX));

        // Visually Flat Simplification
        REPORTER_ASSERT(reporter, pts[12] == SkPoint::Make(10, 10));
        REPORTER_ASSERT(reporter, pts[13] == SkPoint::Make(30, 10)); // Quad flat
        REPORTER_ASSERT(reporter, pts[14] == SkPoint::Make(10, 10)); // Close
        REPORTER_ASSERT(reporter, std::isnan(pts[15].fX));

        REPORTER_ASSERT(reporter, pts[16] == SkPoint::Make(10, 30));
        REPORTER_ASSERT(reporter, pts[17] == SkPoint::Make(30, 30)); // Conic flat
        REPORTER_ASSERT(reporter, pts[18] == SkPoint::Make(10, 30)); // Close
        REPORTER_ASSERT(reporter, std::isnan(pts[19].fX));

        REPORTER_ASSERT(reporter, pts[20] == SkPoint::Make(10, 50));
        REPORTER_ASSERT(reporter, pts[21] == SkPoint::Make(40, 50)); // Cubic flat
        REPORTER_ASSERT(reporter, pts[22] == SkPoint::Make(10, 50)); // Close
        REPORTER_ASSERT(reporter, std::isnan(pts[23].fX));
    }

    // Culling (Entirely top, right, or bottom of the viewport)
    {
        SkPathBuilder builder;
        builder.moveTo(10, -10);
        builder.quadTo(20, -20, 30, -10);

        builder.moveTo(110, 10);
        builder.conicTo(120, 20, 130, 10, 0.5f);

        builder.moveTo(10, 110);
        builder.cubicTo(20, 120, 30, 120, 40, 110);
        SkPath path = builder.detach();

        Flatten flatten;
        Polyline polyline;
        flatten.processPaths<FlattenMode::kScalar>(path, SkMatrix::I(), 100.0f, 100.0f, &polyline);

        // Curves are fully dropped. The implicit close points match the moveTo points
        // exactly, so Polyline drops the close point via deduplication!
        // Expected per contour: Start Pt, NaN. (2 pts * 3 = 6)
        REPORTER_ASSERT(reporter, polyline.count() == 6);
        const auto& pts = polyline.points();

        REPORTER_ASSERT(reporter, pts[0] == SkPoint::Make(10, -10));
        REPORTER_ASSERT(reporter, std::isnan(pts[1].fX));

        REPORTER_ASSERT(reporter, pts[2] == SkPoint::Make(110, 10));
        REPORTER_ASSERT(reporter, std::isnan(pts[3].fX));

        REPORTER_ASSERT(reporter, pts[4] == SkPoint::Make(10, 110));
        REPORTER_ASSERT(reporter, std::isnan(pts[5].fX));
    }

    // Interleaved valid geometry with culling and simplification
    {
        SkPathBuilder builder;

        // Contour 1: Weaves outside to the left and back
        builder.moveTo(10, 10);
        builder.lineTo(20, 10);
        builder.lineTo(-10, 10); // Exits left
        builder.quadTo(-20, 20, -30, 10); // Simplifies to line (-30, 10)
        builder.lineTo(10, 20); // Re-enters viewport

        // Contour 2: Completely culled contour
        builder.moveTo(150, 150);
        builder.cubicTo(160, 160, 170, 160, 180, 150);

        // Contour 3: Valid normal contour
        builder.moveTo(30, 30);
        builder.lineTo(40, 30);

        SkPath path = builder.detach();

        Flatten flatten;
        Polyline polyline;
        flatten.processPaths<FlattenMode::kScalar>(path, SkMatrix::I(), 100.0f, 100.0f, &polyline);

        // Contour 1: moveTo + 3 lineTos + simplified quad + lineTo + close + NaN = 7 points
        // Contour 2: moveTo + NaN (close is deduplicated due to complete culling) = 2 points
        // Contour 3: moveTo + lineTo + close + NaN = 4 points
        // Total expected = 13 points
        REPORTER_ASSERT(reporter, polyline.count() == 13);

        const auto& pts = polyline.points();

        // Verify Contour 1 simplified correctly without dropping points
        REPORTER_ASSERT(reporter, pts[0] == SkPoint::Make(10, 10));
        REPORTER_ASSERT(reporter, pts[3] == SkPoint::Make(-30, 10)); // Simplified Quad
        REPORTER_ASSERT(reporter, pts[4] == SkPoint::Make(10, 20));  // Return line
        REPORTER_ASSERT(reporter, pts[5] == SkPoint::Make(10, 10));  // Implicit close
        REPORTER_ASSERT(reporter, std::isnan(pts[6].fX));

        // Verify Contour 2 was fully culled
        REPORTER_ASSERT(reporter, pts[7] == SkPoint::Make(150, 150));
        REPORTER_ASSERT(reporter, std::isnan(pts[8].fX));

        // Verify Contour 3 generated successfully despite the previous culling
        REPORTER_ASSERT(reporter, pts[9] == SkPoint::Make(30, 30));
        REPORTER_ASSERT(reporter, pts[10] == SkPoint::Make(40, 30));
        REPORTER_ASSERT(reporter, pts[11] == SkPoint::Make(30, 30));
        REPORTER_ASSERT(reporter, std::isnan(pts[12].fX));
    }
}

}  // namespace skgpu::graphite
