/*
 * Copyright 2022 Rive
 */

#include "gmutils.hpp"

#include "rive/math/mat2d.hpp"
#include "rive/math/math_types.hpp"

#include <chrono>
#include <vector>

namespace rivegm
{

double GetCurrSeconds()
{
  auto now = std::chrono::steady_clock::now();
  std::chrono::duration<double> ns = now.time_since_epoch();
  return ns.count();
}

// Approximates with 4 cubics
// see https://spencermortensen.com/articles/bezier-circle/
//
constexpr float C = 0.5519150244935105707435627f;
void path_addOval(rive::RenderPath* path, rive::AABB bounds, PathDirection dir)
{
  // precompute clockwise unit circle, starting and ending at {1, 0}
  constexpr rive::Vec2D unit[] = {
      {1, 0},
      {1, C},
      {C, 1}, // quadrant 1 ( 4:30)
      {0, 1},
      {-C, 1},
      {-1, C}, // quadrant 2 ( 7:30)
      {-1, 0},
      {-1, -C},
      {-C, -1}, // quadrant 3 (10:30)
      {0, -1},
      {C, -1},
      {1, -C}, // quadrant 4 ( 1:30)
      {1, 0},
  };

  const rive::Vec2D center = bounds.center();
  const float dx = center.x;
  const float dy = center.y;
  const float sx = bounds.width() * 0.5f;
  const float sy = bounds.height() * 0.5f;

  auto map = [dx, dy, sx, sy](rive::Vec2D p) {
    return rive::Vec2D(p.x * sx + dx, p.y * sy + dy);
  };

  if (dir == PathDirection::clockwise)
  {
    path->move(map(unit[0]));
    for (int i = 1; i <= 12; i += 3)
    {
      path->cubic(map(unit[i + 0]), map(unit[i + 1]), map(unit[i + 2]));
    }
  }
  else
  {
    path->move(map(unit[12]));
    for (int i = 11; i >= 0; i -= 3)
    {
      path->cubic(map(unit[i - 0]), map(unit[i - 1]), map(unit[i - 2]));
    }
  }
  path->close();
}

void draw_rect(rive::Renderer* r, rive::AABB rect, rive::RenderPaint* paint)
{
  Path path;
  path->moveTo(rect.minX, rect.minY);
  path->lineTo(rect.maxX, rect.minY);
  path->lineTo(rect.maxX, rect.maxY);
  path->lineTo(rect.minX, rect.maxY);
  path->close();

  r->drawPath(path, paint);
}

void draw_oval(rive::Renderer* r, rive::AABB bounds, rive::RenderPaint* paint)
{
  Path path;
  path_addOval(path.get(), bounds);
  r->drawPath(path, paint);
}

void draw_image(rive::Renderer* ren, rive::RenderImage* img, rive::AABB dst)
{
  if (!img)
  {
    return;
  }

  rive::Mat2D mat = rive::Mat2D::fromTranslate(dst.left(), dst.top()) *
                    rive::Mat2D::fromScale(
                        dst.width() / img->width(),
                        dst.height() / img->height());

  ren->save();
  ren->transform(mat);
  ren->drawImage(
      img,
      rive::ImageSampler::LinearClamp(),
      rive::BlendMode::srcOver,
      1);
  ren->restore();
}

void draw_image(
    rive::Renderer* ren,
    rive::RenderImage* img,
    const rive::ImageSampler& options,
    rive::AABB dst)
{
  if (!img)
  {
    return;
  }

  rive::Mat2D mat = rive::Mat2D::fromTranslate(dst.left(), dst.top()) *
                    rive::Mat2D::fromScale(
                        dst.width() / img->width(),
                        dst.height() / img->height());

  ren->save();
  ren->transform(mat);
  ren->drawImage(img, options, rive::BlendMode::srcOver, 1);
  ren->restore();
}

rive::rcp<rive::RenderPath> renderPathFromRawPath(
    rive::RawPath& path,
    const rive::FillRule fillRule)
{
  auto factory = TestingWindow::Get()->factory();
  // this causes crash paths that have a call to addQuad.
  // auto renderPath = factory->makeRenderPath(path, fillRule);
  // this does not crash
  auto renderPath = factory->makeEmptyRenderPath();
  path.addTo(renderPath.get());
  return renderPath;
}

PathBuilder& PathBuilder::fillRule(rive::FillRule f)
{
  m_Path->fillRule(f);
  return *this;
}

PathBuilder& PathBuilder::moveTo(float x, float y)
{
  m_Path->moveTo(x, y);
  m_FirstX = m_LastX = x;
  m_FirstY = m_LastY = y;
  return *this;
}

PathBuilder& PathBuilder::lineTo(float x, float y)
{
  m_Path->lineTo(x, y);
  m_LastX = x;
  m_LastY = y;
  return *this;
}

PathBuilder& PathBuilder::quadTo(float ox, float oy, float x, float y)
{
  m_Path->cubicTo(
      m_LastX + (ox - m_LastX) * (2 / 3.f),
      m_LastY + (oy - m_LastY) * (2 / 3.f),
      x + (ox - x) * (2 / 3.f),
      y + (oy - y) * (2 / 3.f),
      x,
      y);
  m_LastX = x;
  m_LastY = y;
  return *this;
}

PathBuilder& PathBuilder::cubicTo(
    float ox,
    float oy,
    float ix,
    float iy,
    float x,
    float y)
{
  m_Path->cubicTo(ox, oy, ix, iy, x, y);
  m_LastX = x;
  m_LastY = y;
  return *this;
}

PathBuilder& PathBuilder::close()
{
  m_Path->close();
  m_LastX = m_FirstX;
  m_LastY = m_FirstY;
  return *this;
}

PathBuilder& PathBuilder::addRect(rive::AABB rect, PathDirection dir)
{
  float l = rect.left(), t = rect.top(), r = rect.right(), b = rect.bottom();
  moveTo(l, t);
  if (dir == PathDirection::cw)
  {
    lineTo(r, t);
  }
  else
  {
    lineTo(l, b);
  }
  lineTo(r, b);
  if (dir == PathDirection::cw)
  {
    lineTo(l, b);
  }
  else
  {
    lineTo(r, t);
  }
  return close();
}

PathBuilder& PathBuilder::addOval(rive::AABB bounds, PathDirection dir)
{
  path_addOval(m_Path, bounds, dir);
  return *this;
}

PathBuilder& PathBuilder::addCircle(
    float x,
    float y,
    float r,
    PathDirection dir)
{
  return addOval({x - r, y - r, x + r, y + r}, dir);
}

PathBuilder& PathBuilder::addRRect(rive::AABB rect, float radX, float radY)
{
  float l = rect.left(), t = rect.top(), r = rect.right(), b = rect.bottom();
  moveTo(l + radX, t);
  lineTo(r - radX, t);
  cubicTo(r - radX * (1 - C), t, r, t + radY * C, r, t + radY);
  lineTo(r, b - radY);
  cubicTo(r, b - radY * (1 - C), r - radX * (1 - C), b, r - radX, b);
  lineTo(l + radX, b);
  cubicTo(l + radX * C, b, l, b - radY * (1 - C), l, b - radY);
  lineTo(l, t + radY);
  cubicTo(l, t + radY * C, l + radX * C, t, l + radX, t);
  return close();
}

PathBuilder& PathBuilder::addPolygon(
    const std::vector<rive::Vec2D>& pts,
    bool doClose)
{
  moveTo(pts[0].x, pts[0].y);
  for (size_t i = 1; i < pts.size(); ++i)
  {
    lineTo(pts[i].x, pts[i].y);
  }
  if (doClose)
  {
    close();
  }
  return *this;
}

PathBuilder& PathBuilder::polylineTo(const std::vector<rive::Vec2D>& pts)
{
  for (size_t i = 1; i < pts.size(); ++i)
  {
    lineTo(pts[i].x, pts[i].y);
  }
  return *this;
}

rive::rcp<rive::RenderImage> LoadImage(rive::Span<uint8_t> bytes)
{
  return TestingWindow::Get()->factory()->decodeImage(bytes);
}

void path_add_star(Path& path, int count, float anglePhase, float dir)
{
  assert(count & 1);
  float da = 2 * rive::math::PI * (count >> 1) / count;
  float angle = anglePhase;
  for (int i = 0; i < count; ++i)
  {
    rive::Vec2D p = {cosf(angle), sinf(angle)};
    i == 0 ? path->move(p) : path->line(p);
    angle += da * dir;
  }
}

} // namespace rivegm
