/*
 * 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/SkPath.h"
#include "include/core/SkPathBuilder.h"
#include "include/core/SkPoint.h"
#include "include/core/SkScalar.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "include/pathops/SkPathOps.h"
#include "include/private/base/SkTDArray.h"
#include "tests/PathOpsDebug.h"
#include "tests/PathOpsExtendedTest.h"
#include "tests/PathOpsThreadedCommon.h"
#include "tests/Test.h"

#include <atomic>

static int loopNo = 17;

static void add_point(SkString* str, SkScalar x, SkScalar y) {
    int asInt = SkScalarRoundToInt(x);
    if (SkIntToScalar(asInt) == x) {
        str->appendf("%d", asInt);
    } else {
        str->appendf("%1.9gf", x);
    }
    str->appendf(",");
    asInt = SkScalarRoundToInt(y);
    if (SkIntToScalar(asInt) == y) {
        str->appendf("%d", asInt);
    } else {
        str->appendf("%1.9gf", y);
    }
}

static std::atomic<int> gLoopsTestNo{0};

static void testOpLoopsMain(PathOpsThreadState* data) {
    SkASSERT(data);
    PathOpsThreadState& state = *data;
    SkString pathStr;
    for (int a = 0 ; a < 6; ++a) {
        for (int b = a + 1 ; b < 7; ++b) {
            for (int c = 0 ; c < 6; ++c) {
                for (int d = c + 1 ; d < 7; ++d) {
        // define 4 points that form two lines that often cross; one line is (a, b) (c, d)
        SkVector v = {SkIntToScalar(a - c), SkIntToScalar(b - d)};
        SkPoint midA = { SkIntToScalar(a * state.fA + c * (6 - state.fA)) / 6,
                         SkIntToScalar(b * state.fA + d * (6 - state.fA)) / 6 };
        SkPoint midB = { SkIntToScalar(a * state.fB + c * (6 - state.fB)) / 6,
                         SkIntToScalar(b * state.fB + d * (6 - state.fB)) / 6 };
        SkPoint endC = { midA.fX + v.fY * state.fC / 3,
                          midA.fY + v.fX * state.fC / 3 };
        SkPoint endD = { midB.fX - v.fY * state.fD / 3,
                          midB.fY + v.fX * state.fD / 3 };

        SkPath pathA = SkPathBuilder()
                       .moveTo(SkIntToScalar(a), SkIntToScalar(b))
                       .cubicTo({SkIntToScalar(c), SkIntToScalar(d)}, endC, endD)
                       .close()
                       .detach();
        SkPath pathB = SkPathBuilder()
                       .moveTo(SkIntToScalar(c), SkIntToScalar(d))
                       .cubicTo(endC, endD, {SkIntToScalar(a), SkIntToScalar(b)})
                       .close()
                       .detach();
//        SkDebugf("%s\n", pathStr);
        if (state.fReporter->verbose()) {
            pathStr.printf("static void loop%d(skiatest::Reporter* reporter,"
                    " const char* filename) {\n", loopNo);
            pathStr.appendf("    SkPath path, pathB;\n");
            pathStr.appendf("    path.moveTo(%d,%d);\n", a, b);
            pathStr.appendf("    path.cubicTo(%d,%d, ", c, d);
            add_point(&pathStr, endC.fX, endC.fY);
            pathStr.appendf(", ");
            add_point(&pathStr, endD.fX, endD.fY);
            pathStr.appendf(");\n");
            pathStr.appendf("    path.close();\n");
            pathStr.appendf("    pathB.moveTo(%d,%d);\n", c, d);
            pathStr.appendf("    pathB.cubicTo(");
            add_point(&pathStr, endC.fX, endC.fY);
            pathStr.appendf(", ");
            add_point(&pathStr, endD.fX, endD.fY);
            pathStr.appendf(", %d,%d);\n", a, b);
            pathStr.appendf("    pathB.close();\n");
            pathStr.appendf("    testPathOp(reporter, path, pathB, kIntersect_SkPathOp,"
                    " filename);\n");
            pathStr.appendf("}\n");
            state.outputProgress(pathStr.c_str(), kIntersect_SkPathOp);
        }
        SkString testName;
        testName.printf("thread_loops%d", ++gLoopsTestNo);
        testPathOp(state.fReporter, pathA, pathB, kIntersect_SkPathOp, testName.c_str());
        if (PathOpsDebug::gCheckForDuplicateNames) return;
                }
            }
        }
    }
}

DEF_TEST(PathOpsOpLoopsThreaded, reporter) {
    initializeTests(reporter, "loopOp");
    PathOpsThreadedTestRunner testRunner(reporter);
    for (int a = 0; a < 6; ++a) {  // outermost
        for (int b = a + 1; b < 7; ++b) {
            for (int c = 0 ; c < 6; ++c) {
                for (int d = c + 1; d < 7; ++d) {
                    *testRunner.fRunnables.append() =
                            new PathOpsThreadedRunnable(&testOpLoopsMain, a, b, c, d, &testRunner);
                }
            }
            if (!reporter->allowExtendedTest()) goto finish;
        }
    }
finish:
    testRunner.render();
}
