/*
 * 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
