/*
 * Copyright 2011 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 "gm.hpp"
#include "gmutils.hpp"
#include "rive/renderer.hpp"

using namespace rivegm;
using namespace rive;

static constexpr int kPtsCount = 3;
static constexpr Vec2D kPts[kPtsCount] = {
    {40, 40},
    {80, 40},
    {120, 40},
};

static Path make_path_move()
{
    PathBuilder builder;
    for (Vec2D p : kPts)
    {
        builder.moveTo(p.x, p.y);
    }
    return builder.detach();
}

static Path make_path_move_close()
{
    PathBuilder builder;
    for (Vec2D p : kPts)
    {
        builder.moveTo(p.x, p.y).close();
    }
    return builder.detach();
}

static Path make_path_move_line()
{
    PathBuilder builder;
    for (Vec2D p : kPts)
    {
        builder.moveTo(p.x, p.y).lineTo(p.x, p.y);
    }
    return builder.detach();
}

static Path make_path_move_mix()
{
    return PathBuilder()
        .moveTo(kPts[0].x, kPts[0].y)
        .moveTo(kPts[1].x, kPts[1].y)
        .close()
        .moveTo(kPts[2].x, kPts[2].y)
        .lineTo(kPts[2].x, kPts[2].y)
        .detach();
}

class EmptyStrokeGM : public GM
{
public:
    struct Options
    {
        bool stroke = false, feather = false;
    };

    EmptyStrokeGM(Options options) : GM(180, 540), m_options(options) {}

private:
    void onDraw(Renderer* renderer) override
    {
        static constexpr Path (*kProcs[])() = {
            make_path_move,       // expect red red red
            make_path_move_close, // expect black black black
            make_path_move_line,  // expect black black black
            make_path_move_mix,   // expect red black black,
        };

        Paint paint;
        if (m_options.stroke)
        {
            paint->style(RenderPaintStyle::stroke);
            paint->thickness(21);
        }
        if (m_options.feather)
        {
            paint->feather(21);
        }

        Paint dotPaint;
        dotPaint->color(0xffff0000);
        dotPaint->style(RenderPaintStyle::fill);

        for (size_t j = 0; j < 3; ++j)
        {
            paint->cap(static_cast<StrokeCap>((3 - j) % 3));
            paint->join(static_cast<StrokeJoin>(j));
            for (auto proc : kProcs)
            {
                for (int i = 0; i < 3; ++i)
                {
                    renderer->drawPath(PathBuilder::Oval({kPts[i].x - 3.5f,
                                                          kPts[i].y - 3.5f,
                                                          kPts[i].x + 3.5f,
                                                          kPts[i].y + 3.5f}),
                                       dotPaint);
                }
                Path path = proc();
                path->fillRule(FillRule::clockwise);
                renderer->drawPath(path, paint);
                renderer->translate(0, 40);
            }
        }
    }

    Options m_options;
};
GMREGISTER(emptystroke,
           return new EmptyStrokeGM({.stroke = true, .feather = false});)
GMREGISTER(emptyfeather,
           return new EmptyStrokeGM({.stroke = false, .feather = true});)
GMREGISTER(emptystrokefeather,
           return new EmptyStrokeGM({.stroke = true, .feather = true});)
