/*
 * Copyright 2016 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include <initializer_list>
#include <functional>
#include "Test.h"
#if SK_SUPPORT_GPU
#include "GrShape.h"
#include "SkPath.h"
#include "SkDashPathEffect.h"

namespace {
class TestCase {
public:
    TestCase(const SkRRect& rrect, const SkPaint& paint) : fBase(rrect, paint) {
        this->init();
    }

    struct SelfExpectations {
        bool fPEHasEffect;
        bool fPEHasValidKey;
        bool fStrokeApplies;
    };

    void testExpectations(skiatest::Reporter* reporter, SelfExpectations expectations) const;

    enum ComparisonExpecation {
        kAllDifferent_ComparisonExpecation,
        kSameUpToPE_ComparisonExpecation,
        kSameUpToStroke_ComparisonExpecation,
        kAllSame_ComparisonExpecation,
    };

    void compare(skiatest::Reporter*, const TestCase& that, ComparisonExpecation) const;

private:
    void init() {
        fAppliedPE           = fBase.applyPathEffect();
        fAppliedPEThenStroke = fAppliedPE.applyFullStyle();
        fAppliedFull         = fBase.applyFullStyle();

        fBaseKeyIsValid                = MakeKey(&fBaseKey, fBase);
        fAppliedPEKeyIsValid           = MakeKey(&fAppliedPEKey, fAppliedPE);
        fAppliedPEThenStrokeKeyIsValid = MakeKey(&fAppliedPEThenStrokeKey, fAppliedPEThenStroke);
        fAppliedFullKeyIsValid         = MakeKey(&fAppliedFullKey, fAppliedFull);
    }

    using Key = SkTArray<uint32_t>;

    static bool MakeKey(Key* key, const GrShape& shape) {
        int size = shape.unstyledKeySize();
        if (size <= 0) {
            return false;
        }
        key->reset(size);
        shape.writeUnstyledKey(key->begin());
        return true;
    }

    GrShape fBase;
    GrShape fAppliedPE;
    GrShape fAppliedPEThenStroke;
    GrShape fAppliedFull;

    Key fBaseKey;
    Key fAppliedPEKey;
    Key fAppliedPEThenStrokeKey;
    Key fAppliedFullKey;

    bool fBaseKeyIsValid;
    bool fAppliedPEKeyIsValid;
    bool fAppliedPEThenStrokeKeyIsValid;
    bool fAppliedFullKeyIsValid;
};

void TestCase::testExpectations(skiatest::Reporter* reporter, SelfExpectations expectations) const {
    // Applying the path effect and then the stroke should always be the same as applying
    // both in one go.
    REPORTER_ASSERT(reporter, fAppliedPEThenStrokeKey == fAppliedFullKey);
    // The base's key should always be valid (unless the path is volatile)
    REPORTER_ASSERT(reporter, fBaseKeyIsValid);
    if (expectations.fPEHasEffect) {
        REPORTER_ASSERT(reporter, fBaseKey != fAppliedPEKey);
        REPORTER_ASSERT(reporter, expectations.fPEHasEffect == fAppliedPEKeyIsValid);
        REPORTER_ASSERT(reporter, fBaseKey != fAppliedFullKey);
        REPORTER_ASSERT(reporter, expectations.fPEHasEffect == fAppliedFullKeyIsValid);
        if (expectations.fStrokeApplies && expectations.fPEHasValidKey) {
            REPORTER_ASSERT(reporter, fAppliedPEKey != fAppliedFullKey);
            REPORTER_ASSERT(reporter, expectations.fPEHasEffect == fAppliedFullKeyIsValid);
        }
    } else {
        REPORTER_ASSERT(reporter, fBaseKey == fAppliedPEKey);
        if (expectations.fStrokeApplies) {
            REPORTER_ASSERT(reporter, fBaseKey != fAppliedFullKey);
        } else {
            REPORTER_ASSERT(reporter, fBaseKey == fAppliedFullKey);
        }
    }
}

void TestCase::compare(skiatest::Reporter* reporter, const TestCase& that,
                       ComparisonExpecation expectation) const {
    switch (expectation) {
        case kAllDifferent_ComparisonExpecation:
            REPORTER_ASSERT(reporter, fBaseKey != that.fBaseKey);
            REPORTER_ASSERT(reporter, fAppliedPEKey != that.fAppliedPEKey);
            REPORTER_ASSERT(reporter, fAppliedFullKey != that.fAppliedFullKey);
            break;
        case kSameUpToPE_ComparisonExpecation:
            REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey);
            REPORTER_ASSERT(reporter, fAppliedPEKey != that.fAppliedPEKey);
            REPORTER_ASSERT(reporter, fAppliedFullKey != that.fAppliedFullKey);
            break;
        case kSameUpToStroke_ComparisonExpecation:
            REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey);
            REPORTER_ASSERT(reporter, fAppliedPEKey == that.fAppliedPEKey);
            REPORTER_ASSERT(reporter, fAppliedFullKey != that.fAppliedFullKey);
            break;
        case kAllSame_ComparisonExpecation:
            REPORTER_ASSERT(reporter, fBaseKey == that.fBaseKey);
            REPORTER_ASSERT(reporter, fAppliedPEKey == that.fAppliedPEKey);
            REPORTER_ASSERT(reporter, fAppliedFullKey == that.fAppliedFullKey);
            break;
    }
}
}  // namespace

static sk_sp<SkPathEffect> make_dash() {
    static const SkScalar kIntervals[] = { 0.25, 3.f, 0.5, 2.f };
    static const SkScalar kPhase = 0.75;
    return SkDashPathEffect::Make(kIntervals, SK_ARRAY_COUNT(kIntervals), kPhase);
}

static sk_sp<SkPathEffect> make_null_dash() {
    static const SkScalar kNullIntervals[] = {0, 0, 0, 0, 0, 0};
    return SkDashPathEffect::Make(kNullIntervals, SK_ARRAY_COUNT(kNullIntervals), 0.f);
}

static void test_basic(skiatest::Reporter* reporter, const SkRRect& rrect) {
    sk_sp<SkPathEffect> dashPE = make_dash();

    TestCase::SelfExpectations expectations;
    SkPaint fill;

    TestCase fillCase(rrect, fill);
    expectations.fPEHasEffect = false;
    expectations.fPEHasValidKey = false;
    expectations.fStrokeApplies = false;
    fillCase.testExpectations(reporter, expectations);
    // Test that another GrShape instance built from the same primitive is the same.
    TestCase(rrect, fill).compare(reporter, fillCase, TestCase::kAllSame_ComparisonExpecation);

    SkPaint stroke2RoundBevel;
    stroke2RoundBevel.setStyle(SkPaint::kStroke_Style);
    stroke2RoundBevel.setStrokeCap(SkPaint::kRound_Cap);
    stroke2RoundBevel.setStrokeJoin(SkPaint::kBevel_Join);
    stroke2RoundBevel.setStrokeWidth(2.f);
    TestCase stroke2RoundBevelCase(rrect, stroke2RoundBevel);
    expectations.fPEHasValidKey = true;
    expectations.fPEHasEffect = false;
    expectations.fStrokeApplies = true;
    stroke2RoundBevelCase.testExpectations(reporter, expectations);
    TestCase(rrect, stroke2RoundBevel).compare(reporter, stroke2RoundBevelCase,
                                               TestCase::kAllSame_ComparisonExpecation);

    SkPaint stroke2RoundBevelDash = stroke2RoundBevel;
    stroke2RoundBevelDash.setPathEffect(make_dash());
    TestCase stroke2RoundBevelDashCase(rrect, stroke2RoundBevelDash);
    expectations.fPEHasValidKey = true;
    expectations.fPEHasEffect = true;
    expectations.fStrokeApplies = true;
    stroke2RoundBevelDashCase.testExpectations(reporter, expectations);
    TestCase(rrect, stroke2RoundBevelDash).compare(reporter, stroke2RoundBevelDashCase,
                                                   TestCase::kAllSame_ComparisonExpecation);

    fillCase.compare(reporter, stroke2RoundBevelCase,
                     TestCase::kSameUpToStroke_ComparisonExpecation);
    fillCase.compare(reporter, stroke2RoundBevelDashCase,
                     TestCase::kSameUpToPE_ComparisonExpecation);
    stroke2RoundBevelCase.compare(reporter, stroke2RoundBevelDashCase,
                                  TestCase::kSameUpToPE_ComparisonExpecation);
}

template <typename T>
static void test_stroke_param(skiatest::Reporter* reporter, const SkRRect& rrect,
                              std::function<void(SkPaint*, T)> setter, T a, T b) {
    // Set the stroke width so that we don't get hairline. However, call the function second so that
    // it can override.
    SkPaint strokeA;
    strokeA.setStyle(SkPaint::kStroke_Style);
    strokeA.setStrokeWidth(2.f);
    setter(&strokeA, a);
    SkPaint strokeB;
    strokeB.setStyle(SkPaint::kStroke_Style);
    strokeB.setStrokeWidth(2.f);
    setter(&strokeB, b);

    TestCase strokeACase(rrect, strokeA);
    TestCase strokeBCase(rrect, strokeB);
    strokeACase.compare(reporter, strokeBCase, TestCase::kSameUpToStroke_ComparisonExpecation);

    // Make sure stroking params don't affect fill style.
    SkPaint fillA = strokeA, fillB = strokeB;
    fillA.setStyle(SkPaint::kFill_Style);
    fillB.setStyle(SkPaint::kFill_Style);
    TestCase fillACase(rrect, fillA);
    TestCase fillBCase(rrect, fillB);
    fillACase.compare(reporter, fillBCase, TestCase::kAllSame_ComparisonExpecation);

    // Make sure just applying the dash but not stroke gives the same key for both stroking
    // variations.
    SkPaint dashA = strokeA, dashB = strokeB;
    dashA.setPathEffect(make_dash());
    dashB.setPathEffect(make_dash());
    TestCase dashACase(rrect, dashA);
    TestCase dashBCase(rrect, dashB);
    dashACase.compare(reporter, dashBCase, TestCase::kSameUpToStroke_ComparisonExpecation);
}

static void test_miter_limit(skiatest::Reporter* reporter, const SkRRect& rrect) {
    // Miter limit should only matter when stroking with miter joins. It shouldn't affect other
    // joins or fills.
    SkPaint miterA;
    miterA.setStyle(SkPaint::kStroke_Style);
    miterA.setStrokeWidth(2.f);
    miterA.setStrokeJoin(SkPaint::kMiter_Join);
    miterA.setStrokeMiter(0.5f);
    SkPaint miterB = miterA;
    miterA.setStrokeMiter(0.6f);

    TestCase miterACase(rrect, miterA);
    TestCase miterBCase(rrect, miterB);
    miterACase.compare(reporter, miterBCase, TestCase::kSameUpToStroke_ComparisonExpecation);

    SkPaint noMiterA = miterA, noMiterB = miterB;
    noMiterA.setStrokeJoin(SkPaint::kRound_Join);
    noMiterB.setStrokeJoin(SkPaint::kRound_Join);
    TestCase noMiterACase(rrect, noMiterA);
    TestCase noMiterBCase(rrect, noMiterB);
    noMiterACase.compare(reporter, noMiterBCase, TestCase::kAllSame_ComparisonExpecation);

    SkPaint fillA = miterA, fillB = miterB;
    fillA.setStyle(SkPaint::kFill_Style);
    fillB.setStyle(SkPaint::kFill_Style);
    TestCase fillACase(rrect, fillA);
    TestCase fillBCase(rrect, fillB);
    fillACase.compare(reporter, fillBCase, TestCase::kAllSame_ComparisonExpecation);
}

static void test_dash_fill(skiatest::Reporter* reporter, const SkRRect& rrect) {
    // A dash with no stroke should have no effect
    for (auto md : {make_dash, make_null_dash}) {
        SkPaint dashFill;
        dashFill.setPathEffect(md());
        TestCase dashFillCase(rrect, dashFill);

        TestCase fillCase(rrect, SkPaint());
        dashFillCase.compare(reporter, fillCase, TestCase::kAllSame_ComparisonExpecation);
    }
}

void test_null_dash(skiatest::Reporter* reporter, const SkRRect& rrect) {
    SkPaint fill;
    SkPaint stroke;
    stroke.setStyle(SkPaint::kStroke_Style);
    stroke.setStrokeWidth(1.f);
    SkPaint dash;
    dash.setStyle(SkPaint::kStroke_Style);
    dash.setStrokeWidth(1.f);
    dash.setPathEffect(make_dash());
    SkPaint nullDash;
    nullDash.setStyle(SkPaint::kStroke_Style);
    nullDash.setStrokeWidth(1.f);
    nullDash.setPathEffect(make_null_dash());

    TestCase fillCase(rrect, fill);
    TestCase strokeCase(rrect, stroke);
    TestCase dashCase(rrect, dash);
    TestCase nullDashCase(rrect, nullDash);

    nullDashCase.compare(reporter, fillCase, TestCase::kSameUpToStroke_ComparisonExpecation);
    nullDashCase.compare(reporter, strokeCase, TestCase::kAllSame_ComparisonExpecation);
    nullDashCase.compare(reporter, dashCase, TestCase::kSameUpToPE_ComparisonExpecation);
}

DEF_TEST(GrShape, reporter) {
    sk_sp<SkPathEffect> dashPE = make_dash();

    for (auto rr : { SkRRect::MakeRect(SkRect::MakeWH(10, 10)),
                     SkRRect::MakeRectXY(SkRect::MakeWH(10, 10), 3, 4)}) {
        test_basic(reporter, rr);
        test_dash_fill(reporter, rr);
        test_null_dash(reporter, rr);
        // Test modifying various stroke params.
        test_stroke_param<SkScalar>(
                          reporter, rr,
                          [](SkPaint* p, SkScalar w) { p->setStrokeWidth(w);},
                          SkIntToScalar(2), SkIntToScalar(4));
        test_stroke_param<SkPaint::Cap>(
                          reporter, rr,
                          [](SkPaint* p, SkPaint::Cap c) { p->setStrokeCap(c);},
                          SkPaint::kButt_Cap, SkPaint::kRound_Cap);
        test_stroke_param<SkPaint::Join>(
                          reporter, rr,
                          [](SkPaint* p, SkPaint::Join j) { p->setStrokeJoin(j);},
                          SkPaint::kMiter_Join, SkPaint::kRound_Join);
        test_miter_limit(reporter, rr);
    }
}

#endif
