#include "rive/text/text.hpp"
using namespace rive;
#ifdef WITH_RIVE_TEXT
#include "rive/text_engine.hpp"
#include "rive/component_dirt.hpp"
#include "rive/text/utf.hpp"
#include "rive/text/text_style.hpp"
#include "rive/text/text_value_run.hpp"
#include "rive/shapes/paint/shape_paint.hpp"

GlyphItr& GlyphItr::operator++()
{
    m_glyphIndex += m_run->dir == TextDirection::ltr ? 1 : -1;

    // Did we reach the end of the run?
    if (m_glyphIndex == m_line->endGlyphIndex(m_run) && m_run != m_line->lastRun())
    {
        m_run++;
        m_glyphIndex = m_line->startGlyphIndex(m_run);
    }
    return *this;
}

OrderedLine::OrderedLine(const Paragraph& paragraph, const GlyphLine& line) : m_line(&line)
{
    std::vector<const GlyphRun*> logicalRuns;
    const SimpleArray<GlyphRun>& glyphRuns = paragraph.runs;

    for (uint32_t i = line.startRunIndex; i < line.endRunIndex + 1; i++)
    {
        logicalRuns.push_back(&glyphRuns[i]);
    }
    if (paragraph.baseDirection == TextDirection::ltr || logicalRuns.empty())
    {
        m_startLogical = logicalRuns.front();
        m_endLogical = logicalRuns.back();
        m_runs = std::move(logicalRuns);
    }
    else
    {
        std::vector<const GlyphRun*> visualRuns;
        visualRuns.reserve(logicalRuns.size());

        auto itr = logicalRuns.rbegin();
        auto end = logicalRuns.rend();
        const GlyphRun* first = *itr;
        visualRuns.push_back(first);
        size_t ltrIndex = 0;
        TextDirection previousDirection = first->dir;
        while (++itr != end)
        {
            const GlyphRun* run = *itr;
            if (run->dir == TextDirection::ltr && previousDirection == run->dir)
            {
                visualRuns.insert(visualRuns.begin() + ltrIndex, run);
            }
            else
            {
                if (run->dir == TextDirection::ltr)
                {
                    ltrIndex = visualRuns.size();
                }
                visualRuns.push_back(run);
            }
            previousDirection = run->dir;
        }
        m_runs = std::move(visualRuns);
    }
}

void Text::buildRenderStyles()
{
    for (TextStyle* style : m_renderStyles)
    {
        style->resetPath();
    }
    m_renderStyles.clear();

    // Build up ordered runs as we go.
    int paragraphIndex = 0;
    int lineIndex = 0;
    for (const SimpleArray<GlyphLine>& paragraphLines : m_lines)
    {
        const Paragraph& paragraph = m_shape[paragraphIndex++];
        float y = 0.0f;
        for (const GlyphLine& line : paragraphLines)
        {
            if (lineIndex >= m_orderedLines.size())
            {
                // We need to still compute this line's ordered runs.
                m_orderedLines.emplace_back(OrderedLine(paragraph, line));
            }
            const OrderedLine& orderedLine = m_orderedLines[lineIndex];
            float x = 0.0f;
            float renderY = y + line.baseline;
            for (auto glyphItr : orderedLine)
            {
                const GlyphRun* run = std::get<0>(glyphItr);
                size_t glyphIndex = std::get<1>(glyphItr);
                const Font* font = run->font.get();
                GlyphID glyphId = run->glyphs[glyphIndex];

                // TODO: profile if this should be cached.
                RawPath path = font->getPath(glyphId);
                // If we do end up caching these, we'll want to not
                // transformInPlace and just transform instead.
                path.transformInPlace(Mat2D(run->size, 0.0f, 0.0f, run->size, x, renderY));
                x += run->advances[glyphIndex];

                assert(run->styleId < m_runs.size());
                TextStyle* style = m_runs[run->styleId]->style();
                // TextValueRun::onAddedDirty botches loading if it cannot
                // resolve a style, so we're confident we have a style here.
                assert(style != nullptr);
                if (style->addPath(path))
                {
                    // This was the first path added to the style, so let's mark
                    // it in our draw list.
                    m_renderStyles.push_back(style);
                }
            }
            lineIndex++;
        }
    }
}
void Text::draw(Renderer* renderer)
{
    if (!clip(renderer))
    {
        // We didn't clip, so make sure to save as we'll be doing some
        // transformations.
        renderer->save();
    }
    renderer->transform(worldTransform());
    for (auto style : m_renderStyles)
    {
        style->draw(renderer);
    }
    renderer->restore();
}

void Text::addRun(TextValueRun* run) { m_runs.push_back(run); }

void Text::markShapeDirty() { addDirt(ComponentDirt::Path); }

void Text::alignValueChanged() { markShapeDirty(); }

void Text::sizingValueChanged() { markShapeDirty(); }

void Text::overflowValueChanged()
{
    if (sizing() != TextSizing::autoWidth)
    {
        markShapeDirty();
    }
}

void Text::widthChanged()
{
    if (sizing() != TextSizing::autoWidth)
    {
        markShapeDirty();
    }
}

void Text::heightChanged()
{
    if (sizing() == TextSizing::fixed)
    {
        markShapeDirty();
    }
}

static rive::TextRun append(std::vector<Unichar>& unichars,
                            rcp<Font> font,
                            float size,
                            const std::string& text,
                            uint16_t styleId)
{
    const uint8_t* ptr = (const uint8_t*)text.c_str();
    uint32_t n = 0;
    while (*ptr)
    {
        unichars.push_back(UTF::NextUTF8(&ptr));
        n += 1;
    }
    return {std::move(font), size, n, 0, styleId};
}

static SimpleArray<SimpleArray<GlyphLine>> breakLines(const SimpleArray<Paragraph>& paragraphs,
                                                      float width,
                                                      TextAlign align)
{
    bool autoWidth = width == -1.0f;
    float paragraphWidth = width;

    SimpleArray<SimpleArray<GlyphLine>> lines(paragraphs.size());

    size_t paragraphIndex = 0;
    for (auto& para : paragraphs)
    {
        lines[paragraphIndex] = GlyphLine::BreakLines(para.runs, autoWidth ? -1.0f : width);
        if (autoWidth)
        {
            paragraphWidth = std::max(paragraphWidth,
                                      GlyphLine::ComputeMaxWidth(lines[paragraphIndex], para.runs));
        }
        paragraphIndex++;
    }
    paragraphIndex = 0;
    for (auto& para : paragraphs)
    {
        GlyphLine::ComputeLineSpacing(lines[paragraphIndex++], para.runs, paragraphWidth, align);
    }
    return lines;
}

void Text::update(ComponentDirt value)
{
    Super::update(value);

    if (hasDirt(value, ComponentDirt::Path))
    {
        std::vector<Unichar> unichars;
        std::vector<TextRun> runs;
        uint16_t runIndex = 0;
        for (auto valueRun : m_runs)
        {
            auto style = valueRun->style();
            const std::string& text = valueRun->text();
            if (style == nullptr || style->font() == nullptr || text.empty())
            {
                runIndex++;
                continue;
            }
            runs.emplace_back(append(unichars, style->font(), style->fontSize(), text, runIndex++));
        }
        if (!runs.empty())
        {
            m_shape = runs[0].font->shapeText(unichars, runs);
            m_lines = breakLines(m_shape,
                                 sizing() == TextSizing::autoWidth ? -1.0f : width(),
                                 (TextAlign)alignValue());

            m_orderedLines.clear();
        }
        // This could later be flagged as dirty and called only when actually
        // rendered the first time, for now we do it on update cycle in tandem
        // with shaping.
        buildRenderStyles();
    }
}

Core* Text::hitTest(HitInfo*, const Mat2D&)
{
    if (renderOpacity() == 0.0f)
    {
        return nullptr;
    }

    return nullptr;
}

#else
// Text disabled.
void Text::draw(Renderer* renderer) {}
Core* Text::hitTest(HitInfo*, const Mat2D&) { return nullptr; }
void Text::addRun(TextValueRun* run) {}
void Text::markShapeDirty() {}
void Text::update(ComponentDirt value) {}
void Text::alignValueChanged() {}
void Text::sizingValueChanged() {}
void Text::overflowValueChanged() {}
void Text::widthChanged() {}
void Text::heightChanged() {}
#endif