/*
 * 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 = std::vector<RenderGlyphRun>;
using RenderFontFactory = rcp<RenderFont> (*)(const Span<const uint8_t>);

template <typename Handler>
void visit(const std::vector<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 std::vector<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>();
}
