/*
 * Copyright 2022 Rive
 */

#include "viewer/viewer_content.hpp"
#include "utils/rive_utf.hpp"

#include "rive/math/raw_path.hpp"
#include "rive/refcnt.hpp"
#include "rive/factory.hpp"
#include "rive/render_text.hpp"
#include "rive/math/contour_measure.hpp"
#include "rive/text/line_breaker.hpp"

using namespace rive;

using RenderFontTextRuns = std::vector<RenderTextRun>;
using RenderFontGlyphRuns = rive::SimpleArray<RenderGlyphRun>;
using RenderFontFactory = rcp<RenderFont> (*)(const Span<const uint8_t>);

template <typename Handler>
void visit(const Span<RenderGlyphRun>& gruns, Vec2D origin, Handler proc) {
    for (const auto& gr : gruns) {
        for (size_t i = 0; i < gr.glyphs.size(); ++i) {
            auto path = gr.font->getPath(gr.glyphs[i]);
            auto mx = Mat2D::fromTranslate(origin.x + gr.xpos[i], origin.y) *
                      Mat2D::fromScale(gr.size, gr.size);
            path.transformInPlace(mx);
            proc(path);
        }
    }
}

static Vec2D ave(Vec2D a, Vec2D b) { return (a + b) * 0.5f; }

static RawPath make_quad_path(Span<const Vec2D> pts) {
    const int N = pts.size();
    RawPath path;
    if (N >= 2) {
        path.move(pts[0]);
        if (N == 2) {
            path.line(pts[1]);
        } else if (N == 3) {
            path.quad(pts[1], pts[2]);
        } else {
            for (int i = 1; i < N - 2; ++i) {
                path.quad(pts[i], ave(pts[i], pts[i + 1]));
            }
            path.quad(pts[N - 2], pts[N - 1]);
        }
    }
    return path;
}

static void warp_in_place(ContourMeasure* meas, RawPath* path) {
    for (auto& pt : path->points()) {
        pt = meas->warp(pt);
    }
}

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

static std::unique_ptr<RenderPath> make_rpath(RawPath& path) {
    return ViewerContent::RiveFactory()->makeRenderPath(path, FillRule::nonZero);
}

static void stroke_path(Renderer* renderer, RawPath& path, float size, ColorInt color) {
    auto paint = ViewerContent::RiveFactory()->makeRenderPaint();
    paint->color(color);
    paint->thickness(size);
    paint->style(RenderPaintStyle::stroke);
    renderer->drawPath(make_rpath(path).get(), paint.get());
}

static void fill_rect(Renderer* renderer, const AABB& r, RenderPaint* paint) {
    RawPath rp;
    rp.addRect(r);
    renderer->drawPath(make_rpath(rp).get(), paint);
}

static void fill_point(Renderer* renderer, Vec2D p, float r, RenderPaint* paint) {
    fill_rect(renderer, {p.x - r, p.y - r, p.x + r, p.y + r}, paint);
}

static RenderTextRun
append(std::vector<Unichar>* unichars, rcp<RenderFont> font, float size, const char text[]) {
    const uint8_t* ptr = (const uint8_t*)text;
    uint32_t n = 0;
    while (*ptr) {
        unichars->push_back(rive::UTF::NextUTF8(&ptr));
        n += 1;
    }
    return {std::move(font), size, n};
}

class TextPathContent : public ViewerContent {
    std::vector<Unichar> m_unichars;
    RenderFontGlyphRuns m_gruns;
    std::unique_ptr<RenderPaint> m_paint;
    AABB m_gbounds;

    std::vector<Vec2D> m_pathpts;
    Vec2D m_lastPt = {0, 0};
    int m_trackingIndex = -1;
    Mat2D m_trans;

    Mat2D m_oneLineXform;
    bool m_trackingOneLine = false;
    float m_oneLineX = 0;
    float m_flareRadius = 50;

    float m_alignment = 0, m_scaleY = 1, m_offsetY = 0,
          m_windowWidth = 1, // %
        m_windowOffset = 0;  // %

    RenderFontTextRuns make_truns(RenderFontFactory fact) {
        auto loader = [fact](const char filename[]) -> rcp<RenderFont> {
            auto bytes = ViewerContent::LoadFile(filename);
            if (bytes.size() == 0) {
                assert(false);
                return nullptr;
            }
            return fact(bytes);
        };

        const char* fontFiles[] = {
            "../../../test/assets/RobotoFlex.ttf",
            "../../../test/assets/LibreBodoni-Italic-VariableFont_wght.ttf",
        };

        auto font0 = loader(fontFiles[0]);
        auto font1 = loader(fontFiles[1]);
        assert(font0);
        assert(font1);

        RenderFont::Coord c1 = {'wght', 100.f}, c2 = {'wght', 800.f};

        RenderFontTextRuns truns;

        truns.push_back(append(&m_unichars, font0->makeAtCoord(c2), 60, "U"));
        truns.push_back(append(&m_unichars, font0->makeAtCoord(c1), 30, "ne漢字asy"));
        truns.push_back(append(&m_unichars, font1, 30, " fits the crown"));
        truns.push_back(append(&m_unichars, font1->makeAtCoord(c1), 30, " that often"));
        truns.push_back(append(&m_unichars, font0, 30, " lies the head."));

        return truns;
    }

public:
    TextPathContent() {
        auto compute_bounds = [](const rive::SimpleArray<RenderGlyphRun>& gruns) {
            AABB bounds = {};
            for (const auto& gr : gruns) {
                bounds.minY = std::min(bounds.minY, gr.font->lineMetrics().ascent * gr.size);
                bounds.maxY = std::max(bounds.maxY, gr.font->lineMetrics().descent * gr.size);
            }
            bounds.minX = gruns.front().xpos.front();
            bounds.maxX = gruns.back().xpos.back();
            printf("%g %g %g %g\n", bounds.left(), bounds.top(), bounds.right(), bounds.bottom());
            return bounds;
        };

        auto truns = this->make_truns(ViewerContent::DecodeFont);

        m_gruns = truns[0].font->shapeText(m_unichars, truns);

        m_gbounds = compute_bounds(m_gruns);
        m_oneLineXform = Mat2D::fromScale(2.5, 2.5) * Mat2D::fromTranslate(20, 80);

        m_paint = ViewerContent::RiveFactory()->makeRenderPaint();
        m_paint->color(0xFFFFFFFF);

        m_pathpts.push_back({20, 300});
        m_pathpts.push_back({220, 100});
        m_pathpts.push_back({420, 500});
        m_pathpts.push_back({620, 100});
        m_pathpts.push_back({820, 300});

        m_trans = Mat2D::fromTranslate(200, 200) * Mat2D::fromScale(2, 2);
    }

    void draw_warp(Renderer* renderer, RawPath& warp) {
        stroke_path(renderer, warp, 0.5, 0xFF00FF00);

        auto paint = ViewerContent::RiveFactory()->makeRenderPaint();
        paint->color(0xFF008800);
        const float r = 4;
        for (auto p : m_pathpts) {
            fill_point(renderer, p, r, paint.get());
        }
    }

    static size_t count_glyphs(const RenderFontGlyphRuns& gruns) {
        size_t n = 0;
        for (const auto& gr : gruns) {
            n += gr.glyphs.size();
        }
        return n;
    }

    void modify(float amount) { m_paint->color(0xFFFFFFFF); }

    void draw(Renderer* renderer, const RenderFontGlyphRuns& gruns) {
        auto get_path = [this](const RenderGlyphRun& run, int index, float dx) {
            auto path = run.font->getPath(run.glyphs[index]);
            path.transformInPlace(Mat2D::fromTranslate(run.xpos[index] + dx, m_offsetY) *
                                  Mat2D::fromScale(run.size, run.size * m_scaleY));
            return path;
        };

        renderer->save();
        renderer->transform(m_trans);

        RawPath warp = make_quad_path(m_pathpts);
        this->draw_warp(renderer, warp);

        auto meas = ContourMeasureIter(warp).next();

        const float warpLength = meas->length();
        const float textLength = gruns.back().xpos.back();
        const float offset = (warpLength - textLength) * m_alignment;

        const size_t glyphCount = count_glyphs(gruns);
        size_t glyphIndex = 0;
        float windowEnd = m_windowOffset + m_windowWidth;

        for (const auto& gr : gruns) {
            for (size_t i = 0; i < gr.glyphs.size(); ++i) {
                float percent = glyphIndex / (float)(glyphCount - 1);
                float amount = (percent >= m_windowOffset && percent <= windowEnd);

                float scaleY = m_scaleY;
                m_paint->color(0xFF666666);
                m_paint->style(RenderPaintStyle::fill);
                if (amount > 0) {
                    this->modify(amount);
                }

                auto path = get_path(gr, i, offset);
                warp_in_place(meas.get(), &path);
                renderer->drawPath(make_rpath(path).get(), m_paint.get());
                glyphIndex += 1;
                m_scaleY = scaleY;
            }
        }
        renderer->restore();
    }

    void drawOneLine(Renderer* renderer) {
        auto paint = ViewerContent::RiveFactory()->makeRenderPaint();
        paint->color(0xFF88FFFF);

        if (m_trackingOneLine) {
            float mx = m_oneLineX / m_gbounds.width();
            const ColorInt colors[] = {0xFF88FFFF, 0xFF88FFFF, 0xFFFFFFFF, 0xFF88FFFF, 0xFF88FFFF};
            const float stops[] = {0, mx / 2, mx, (1 + mx) / 2, 1};
            paint->shader(ViewerContent::RiveFactory()->makeLinearGradient(m_gbounds.left(),
                                                                           0,
                                                                           m_gbounds.right(),
                                                                           0,
                                                                           colors,
                                                                           stops,
                                                                           5));
        }

        struct EaseWindow {
            float center, radius;

            float map(float x) const {
                float dist = std::abs(center - x);
                if (dist > radius) {
                    return 0;
                }
                float t = (radius - dist) / radius;
                return t * t * (3 - 2 * t);
            }
        };

        auto wrap_path = [](const RawPath& src, float x, float rad) {
            return src.morph([x, rad](Vec2D p) {
                Vec2D newpt = p;
                newpt.y = p.y * 4 + 18;

                const float t = EaseWindow{x, rad}.map(p.x);
                return Vec2D::lerp(p, newpt, t);
            });
        };

        visit(m_gruns, {0, 0}, [&](RawPath& rp) {
            RawPath* ptr = &rp;
            RawPath storage;
            if (m_trackingOneLine) {
                storage = wrap_path(rp, m_oneLineX, m_flareRadius);
                ptr = &storage;
            }
            renderer->drawPath(make_rpath(*ptr).get(), paint.get());
        });
    }

    void handleDraw(rive::Renderer* renderer, double) override {
        renderer->save();
        this->draw(renderer, m_gruns);
        renderer->restore();

        renderer->save();
        renderer->transform(m_oneLineXform);
        this->drawOneLine(renderer);
        renderer->restore();
    }

    void handlePointerMove(float x, float y) override {
        auto contains = [](const AABB& r, Vec2D p) {
            return r.left() <= p.x && p.x < r.right() && r.top() <= p.y && p.y < r.bottom();
        };

        // are we on onLine?
        {
            m_trackingOneLine = false;
            auto pos = m_oneLineXform.invertOrIdentity() * Vec2D{x, y};
            if (contains(m_gbounds.inset(-8, 0), pos)) {
                m_trackingOneLine = true;
                m_oneLineX = pos.x;
                return;
            }
        }

        // are we on the path?
        m_lastPt = m_trans.invertOrIdentity() * Vec2D{x, y};
        if (m_trackingIndex >= 0) {
            m_pathpts[m_trackingIndex] = m_lastPt;
        }
    }
    void handlePointerDown(float x, float y) override {
        auto close_to = [](Vec2D a, Vec2D b) { return Vec2D::distance(a, b) <= 10; };
        for (size_t i = 0; i < m_pathpts.size(); ++i) {
            if (close_to(m_lastPt, m_pathpts[i])) {
                m_trackingIndex = i;
                break;
            }
        }
    }

    void handlePointerUp(float x, float y) override { m_trackingIndex = -1; }

    void handleResize(int width, int height) override {}

    void handleImgui() override {
        ImGui::Begin("path", nullptr);
        ImGui::SliderFloat("Alignment", &m_alignment, -3, 4);
        ImGui::SliderFloat("Scale Y", &m_scaleY, 0.25f, 3.0f);
        ImGui::SliderFloat("Offset Y", &m_offsetY, -100, 100);
        ImGui::SliderFloat("Window Offset", &m_windowOffset, -1.1f, 1.1f);
        ImGui::SliderFloat("Window Width", &m_windowWidth, 0, 1.2f);
        ImGui::SliderFloat("Flare radius", &m_flareRadius, 10, 100);
        ImGui::End();
    }
};

std::unique_ptr<ViewerContent> ViewerContent::TextPath(const char filename[]) {
    return std::make_unique<TextPathContent>();
}
