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