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

#include "gm/gm.h"
#include "include/core/SkCanvas.h"
#include "include/core/SkColor.h"
#include "include/core/SkPaint.h"
#include "include/core/SkPath.h"
#include "include/core/SkPoint.h"
#include "include/core/SkScalar.h"
#include "include/core/SkSize.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "src/base/SkRandom.h"
#include "src/core/SkGeometry.h"

#include <math.h>

namespace skiagm {

// Slices paths into sliver-size contours shaped like ice cream cones.
class MandolineSlicer {
public:
    inline static constexpr int kDefaultSubdivisions = 10;

    MandolineSlicer(SkPoint anchorPt) {
        fPath.setFillType(SkPathFillType::kEvenOdd);
        fPath.setIsVolatile(true);
        this->reset(anchorPt);
    }

    void reset(SkPoint anchorPt) {
        fPath.reset();
        fLastPt = fAnchorPt = anchorPt;
    }

    void sliceLine(SkPoint pt, int numSubdivisions = kDefaultSubdivisions) {
        if (numSubdivisions <= 0) {
            fPath.moveTo(fAnchorPt);
            fPath.lineTo(fLastPt);
            fPath.lineTo(pt);
            fPath.close();
            fLastPt = pt;
            return;
        }
        float T = this->chooseChopT(numSubdivisions);
        if (0 == T) {
            return;
        }
        SkPoint midpt = fLastPt * (1 - T) + pt * T;
        this->sliceLine(midpt, numSubdivisions - 1);
        this->sliceLine(pt, numSubdivisions - 1);
    }

    void sliceQuadratic(SkPoint p1, SkPoint p2, int numSubdivisions = kDefaultSubdivisions) {
        if (numSubdivisions <= 0) {
            fPath.moveTo(fAnchorPt);
            fPath.lineTo(fLastPt);
            fPath.quadTo(p1, p2);
            fPath.close();
            fLastPt = p2;
            return;
        }
        float T = this->chooseChopT(numSubdivisions);
        if (0 == T) {
            return;
        }
        SkPoint P[3] = {fLastPt, p1, p2}, PP[5];
        SkChopQuadAt(P, PP, T);
        this->sliceQuadratic(PP[1], PP[2], numSubdivisions - 1);
        this->sliceQuadratic(PP[3], PP[4], numSubdivisions - 1);
    }

    void sliceCubic(SkPoint p1, SkPoint p2, SkPoint p3,
                    int numSubdivisions = kDefaultSubdivisions) {
        if (numSubdivisions <= 0) {
            fPath.moveTo(fAnchorPt);
            fPath.lineTo(fLastPt);
            fPath.cubicTo(p1, p2, p3);
            fPath.close();
            fLastPt = p3;
            return;
        }
        float T = this->chooseChopT(numSubdivisions);
        if (0 == T) {
            return;
        }
        SkPoint P[4] = {fLastPt, p1, p2, p3}, PP[7];
        SkChopCubicAt(P, PP, T);
        this->sliceCubic(PP[1], PP[2], PP[3], numSubdivisions - 1);
        this->sliceCubic(PP[4], PP[5], PP[6], numSubdivisions - 1);
    }

    void sliceConic(SkPoint p1, SkPoint p2, float w, int numSubdivisions = kDefaultSubdivisions) {
        if (numSubdivisions <= 0) {
            fPath.moveTo(fAnchorPt);
            fPath.lineTo(fLastPt);
            fPath.conicTo(p1, p2, w);
            fPath.close();
            fLastPt = p2;
            return;
        }
        float T = this->chooseChopT(numSubdivisions);
        if (0 == T) {
            return;
        }
        SkConic conic(fLastPt, p1, p2, w), halves[2];
        if (!conic.chopAt(T, halves)) {
            SK_ABORT("SkConic::chopAt failed");
        }
        this->sliceConic(halves[0].fPts[1], halves[0].fPts[2], halves[0].fW, numSubdivisions - 1);
        this->sliceConic(halves[1].fPts[1], halves[1].fPts[2], halves[1].fW, numSubdivisions - 1);
    }

    const SkPath& path() const { return fPath; }

private:
    float chooseChopT(int numSubdivisions) {
        SkASSERT(numSubdivisions > 0);
        if (numSubdivisions > 1) {
            return .5f;
        }
        float T = (0 == fRand.nextU() % 10) ? 0 : scalbnf(1, -(int)fRand.nextRangeU(10, 149));
        SkASSERT(T >= 0 && T < 1);
        return T;
    }

    SkRandom fRand;
    SkPath fPath;
    SkPoint fAnchorPt;
    SkPoint fLastPt;
};

class SliverPathsGM : public GM {
public:
    SliverPathsGM() {
        this->setBGColor(SK_ColorBLACK);
    }

protected:
    SkString onShortName() override {
        return SkString("mandoline");
    }

    SkISize onISize() override {
        return SkISize::Make(560, 475);
    }

    void onDraw(SkCanvas* canvas) override {
        SkPaint paint;
        paint.setColor(SK_ColorWHITE);
        paint.setAntiAlias(true);

        MandolineSlicer mandoline({41, 43});
        mandoline.sliceCubic({5, 277}, {381, -74}, {243, 162});
        mandoline.sliceLine({41, 43});
        canvas->drawPath(mandoline.path(), paint);

        mandoline.reset({357.049988f, 446.049988f});
        mandoline.sliceCubic({472.750000f, -71.950012f}, {639.750000f, 531.950012f},
                             {309.049988f, 347.950012f});
        mandoline.sliceLine({309.049988f, 419});
        mandoline.sliceLine({357.049988f, 446.049988f});
        canvas->drawPath(mandoline.path(), paint);

        canvas->save();
        canvas->translate(421, 105);
        canvas->scale(100, 81);
        mandoline.reset({-cosf(SkDegreesToRadians(-60)), sinf(SkDegreesToRadians(-60))});
        mandoline.sliceConic({-2, 0},
                             {-cosf(SkDegreesToRadians(60)), sinf(SkDegreesToRadians(60))}, .5f);
        mandoline.sliceConic({-cosf(SkDegreesToRadians(120))*2, sinf(SkDegreesToRadians(120))*2},
                             {1, 0}, .5f);
        mandoline.sliceLine({0, 0});
        mandoline.sliceLine({-cosf(SkDegreesToRadians(-60)), sinf(SkDegreesToRadians(-60))});
        canvas->drawPath(mandoline.path(), paint);
        canvas->restore();

        canvas->save();
        canvas->translate(150, 300);
        canvas->scale(75, 75);
        mandoline.reset({1, 0});
        constexpr int nquads = 5;
        for (int i = 0; i < nquads; ++i) {
            float theta1 = 2*SK_ScalarPI/nquads * (i + .5f);
            float theta2 = 2*SK_ScalarPI/nquads * (i + 1);
            mandoline.sliceQuadratic({cosf(theta1)*2, sinf(theta1)*2},
                                     {cosf(theta2), sinf(theta2)});
        }
        canvas->drawPath(mandoline.path(), paint);
        canvas->restore();
    }
};

DEF_GM(return new SliverPathsGM;)

}  // namespace skiagm
