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

#include <cassert>

#include "gm.hpp"
#include "gmutils.hpp"
#include "rive/renderer.hpp"
#include "rive/math/mat2d.hpp"
#include "rive/math/math_types.hpp"
#include "rive/math/vec2d.hpp"

using namespace rivegm;
using namespace rive;

constexpr int kNumColumns = 3;
constexpr int kNumPaints = 2;
constexpr int kNumRows = 5;
constexpr int kRadius = 40; // radius of the snowflake
constexpr int kPad = 5;     // padding on both sides of the snowflake
constexpr int kNumSpokes = 6;
constexpr float kStrokeWidth = 5.0f;

static void draw_fins(Renderer* renderer,
                      const Vec2D& offset,
                      float angle,
                      RenderPaint* paint)
{
    float cos, sin;

    // first fin
    sin = sinf(angle + (math::PI / 4));
    cos = cosf(angle + (math::PI / 4));
    sin *= kRadius / 2.0f;
    cos *= kRadius / 2.0f;

    Path p;
    p->moveTo(offset.x, offset.y);
    p->lineTo(offset.x + cos, offset.y + sin);
    renderer->drawPath(p, paint);

    // second fin
    sin = sinf(angle - (math::PI / 4));
    cos = cosf(angle - (math::PI / 4));
    sin *= kRadius / 2.0f;
    cos *= kRadius / 2.0f;

    p = Path();
    p->moveTo(offset.x, offset.y);
    p->lineTo(offset.x + cos, offset.y + sin);
    renderer->drawPath(p, paint);
}

// draw a snowflake centered at the origin
static void draw_snowflake(Renderer* renderer, RenderPaint* paint)
{
    renderer->clipPath(PathBuilder::Rect(
        {-kRadius - kPad, -kRadius - kPad, kRadius + kPad, kRadius + kPad}));

    float sin, cos, angle = 0.0f;
    for (int i = 0; i < kNumSpokes / 2;
         ++i, angle += math::PI / (int)(kNumSpokes / 2))
    {
        sin = sinf(angle);
        cos = cosf(angle);
        sin *= kRadius;
        cos *= kRadius;

        // main spoke
        Path p;
        p->moveTo(-cos, -sin);
        p->lineTo(cos, sin);
        renderer->drawPath(p, paint);

        // fins on positive side
        const Vec2D posOffset = Vec2D(0.5f * cos, 0.5f * sin);
        draw_fins(renderer, posOffset, angle, paint);

        // fins on negative side
        const Vec2D negOffset = Vec2D(-0.5f * cos, -0.5f * sin);
        draw_fins(renderer, negOffset, angle + math::PI, paint);
    }
}

static void draw_row(Renderer* renderer,
                     RenderPaint* paint,
                     const Mat2D& localMatrix)
{
    renderer->translate(kRadius + kPad, 0.0f);

    for (auto cap : {StrokeCap::butt, StrokeCap::round, StrokeCap::square})
    {
        paint->thickness(kStrokeWidth);
        paint->style(RenderPaintStyle::stroke);
        paint->cap(cap);

        renderer->save();
        renderer->transform(localMatrix);
        draw_snowflake(renderer, paint);
        renderer->restore();

        renderer->translate(2 * (kRadius + kPad), 0.0f);
    }
}

namespace skiagm
{

// This GM exercises the special case of a stroked lines.
// Various shaders are applied to ensure the coordinate spaces work out right.
class StrokedLinesGM : public GM
{
public:
    StrokedLinesGM() :
        GM(kNumColumns * (2 * kRadius + 2 * kPad),
           kNumRows * (2 * kRadius + 2 * kPad))
    {}

protected:
    void onOnceBeforeDraw() override
    {
        // paints
        {
            // basic white
            fPaints[0]->color(0xffffffff);
        }
        {
            // gradient
            ColorInt colors[] = {0xffff0000, 0xff00ff00};
            Vec2D pts[] = {{-kRadius - kPad, -kRadius - kPad},
                           {kRadius + kPad, kRadius + kPad}};
            float stops[] = {0, 1};

            auto sh =
                TestingWindow::Get()->factory()->makeLinearGradient(pts[0].x,
                                                                    pts[0].y,
                                                                    pts[1].x,
                                                                    pts[1].y,
                                                                    colors,
                                                                    stops,
                                                                    2);
            fPaints[1]->shader(sh);
        }
        // {
        //     // dashing
        //     float intervals[] = {kStrokeWidth, kStrokeWidth};
        //     int intervalCount = (int)SK_ARRAY_COUNT(intervals);
        //     SkPaint p;
        //     p.setColor(SK_ColorWHITE);
        //     p.setPathEffect(SkDashPathEffect::Make(intervals, intervalCount,
        //     kStrokeWidth));
        //
        //     fPaints.push_back(p);
        // }
        // {
        //     // Bitmap shader
        //     SkBitmap bm;
        //     bm.allocN32Pixels(2, 2);
        //     *bm.getAddr32(0, 0) = *bm.getAddr32(1, 1) = 0xFFFFFFFF;
        //     *bm.getAddr32(1, 0) = *bm.getAddr32(0, 1) = 0x0;
        //
        //     SkMatrix m;
        //     m.setRotate(12.0f);
        //     m.preScale(3.0f, 3.0f);
        //
        //     SkPaint p;
        //     p.setShader(
        //         bm.makeShader(SkTileMode::kRepeat, SkTileMode::kRepeat,
        //         SkSamplingOptions(), m));
        //     fPaints.push_back(p);
        // }
        // {
        //     // blur
        //     SkPaint p;
        //     p.setColor(SK_ColorWHITE);
        //     p.setMaskFilter(SkMaskFilter::MakeBlur(kOuter_SkBlurStyle, 3.0f));
        //     fPaints.push_back(p);
        // }

        // matrices
        {
            // rotation
            Mat2D m = Mat2D::fromRotation(12.0f * math::PI / 180);

            fMatrices.push_back(m);
        }
        {
            // skew
            Mat2D m;
            m.xy(0.5f);
            m.yx(0.3f);

            fMatrices.push_back(m);
        }
        {
            // perspective - not supported
            Mat2D m;

            fMatrices.push_back(m);
        }

        assert(kNumRows == kNumPaints + fMatrices.size());
    }

    ColorInt clearColor() const override { return 0xFF1A65D7; }

    void onDraw(rive::Renderer* renderer) override
    {
        renderer->translate(0, kRadius + kPad);

        for (int i = 0; i < kNumPaints; ++i)
        {
            renderer->save();
            draw_row(renderer, fPaints[i], Mat2D());
            renderer->restore();

            renderer->translate(0, 2 * (kRadius + kPad));
        }

        for (size_t i = 0; i < fMatrices.size(); ++i)
        {
            renderer->save();
            draw_row(renderer, fPaints[0], fMatrices[i]);
            renderer->restore();

            renderer->translate(0, 2 * (kRadius + kPad));
        }
    }

private:
    Paint fPaints[kNumPaints];
    std::vector<Mat2D> fMatrices;

    using INHERITED = GM;
};

//////////////////////////////////////////////////////////////////////////////

GMREGISTER(strokedlines, return new StrokedLinesGM;)
} // namespace skiagm
