/*
 * Copyright 2014 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */
#include "include/core/SkTypes.h"
#include "include/private/SkMalloc.h"
#include "include/private/SkTDArray.h"
#include "src/pathops/SkIntersections.h"
#include "src/pathops/SkPathOpsCubic.h"
#include "src/pathops/SkPathOpsLine.h"
#include "src/pathops/SkPathOpsPoint.h"
#include "tests/PathOpsTestCommon.h"
#include "tests/Test.h"

#include <array>

// check intersections for consistency

struct Curve {
    int ptCount;
    CubicPts curve;  // largest can hold lines / quads/ cubics
};

static const Curve testSet0[] = {  // extracted from skpClip2
    {4, {{{134,11414}, {131.990234,11414}, {130.32666,11415.4824}, {130.042755,11417.4131}}} },
    {4, {{{130.042755,11417.4131}, {130.233124,11418.3193}, {131.037079,11419}, {132,11419}}} },
    {4, {{{132,11419}, {130.895432,11419}, {130,11418.1045}, {130,11417}}} },
};

static const Curve testSet1[] = {  // extracted from cubicOp85i
    {4, {{{3,4}, {1,5}, {4,3}, {6,4}}} },
    {1, {{{6,4}, {3,4}}} },
    {4, {{{3,4}, {4,6}, {4,3}, {5,1}}} },
    {1, {{{5,1}, {3,4}}} },
};

struct TestSet {
    const Curve* tests;
    int testCount;
};
static const auto testSets = std::to_array<TestSet>({
        TestSet{testSet0, (int)std::size(testSet0)},
        TestSet{testSet1, (int)std::size(testSet1)},
});

static const int testSetsCount = (int) std::size(testSets);

static void testSetTest(skiatest::Reporter* reporter, int index) {
    const TestSet& testSet = testSets[index];
    int testCount = testSet.testCount;
    SkASSERT(testCount > 1);
    SkTDArray<SkIntersections> combos;
    for (int outer = 0; outer < testCount - 1; ++outer) {
        const Curve& oTest = testSet.tests[outer];
        for (int inner = outer + 1; inner < testCount; ++inner) {
            const Curve& iTest = testSet.tests[inner];
            SkIntersections* i = combos.append();
            sk_bzero(i, sizeof(SkIntersections));
            SkDLine oLine = {{ oTest.curve.fPts[0], oTest.curve.fPts[1] }};
            SkDLine iLine = {{ iTest.curve.fPts[0], iTest.curve.fPts[1] }};
            SkDCubic iCurve, oCurve;
            iCurve.debugSet(iTest.curve.fPts);
            oCurve.debugSet(oTest.curve.fPts);
            if (oTest.ptCount == 1 && iTest.ptCount == 1) {
                i->intersect(oLine, iLine);
            } else if (oTest.ptCount == 1 && iTest.ptCount == 4) {
                i->intersect(iCurve, oLine);
            } else if (oTest.ptCount == 4 && iTest.ptCount == 1) {
                i->intersect(oCurve, iLine);
            } else if (oTest.ptCount == 4 && iTest.ptCount == 4) {
                i->intersect(oCurve, iCurve);
            } else {
                SkASSERT(0);
            }
//            i->dump();
        }
    }
}

DEF_TEST(PathOpsThreeWay, reporter) {
    for (int index = 0; index < testSetsCount; ++index) {
        testSetTest(reporter, index);
        reporter->bumpTestCount();
    }
}

DEF_TEST(PathOpsThreeWayOneOff, reporter) {
    int index = 0;
    testSetTest(reporter, index);
}
