/*
 * Copyright 2022 Rive
 */

#include "rive/text/line_breaker.hpp"
#include <limits>
using namespace rive;

static bool autowidth(float width) { return width < 0.0f; }
void RenderGlyphLine::ComputeLineSpacing(Span<RenderGlyphLine> lines,
                                         Span<const RenderGlyphRun> runs,
                                         float width,
                                         RenderTextAlign align)
{

    float maxLineWidth = 0.0f;
    if (autowidth(width))
    {
        for (auto& line : lines)
        {
            auto lineWidth =
                runs[line.endRun].xpos[line.endIndex] - runs[line.startRun].xpos[line.startIndex];
            if (lineWidth > maxLineWidth)
            {
                maxLineWidth = lineWidth;
            }
        }
    }
    else
    {
        maxLineWidth = width;
    }
    float Y = 0; // top of our frame
    for (auto& line : lines)
    {
        float asc = 0;
        float des = 0;
        for (int i = line.startRun; i <= line.endRun; ++i)
        {
            const auto& run = runs[i];

            asc = std::min(asc, run.font->lineMetrics().ascent * run.size);
            des = std::max(des, run.font->lineMetrics().descent * run.size);
        }
        line.top = Y;
        Y -= asc;
        line.baseline = Y;
        Y += des;
        line.bottom = Y;
        auto lineWidth =
            runs[line.endRun].xpos[line.endIndex] - runs[line.startRun].xpos[line.startIndex];
        switch (align)
        {
            case RenderTextAlign::right:
                line.startX = maxLineWidth - lineWidth;
                break;
            case RenderTextAlign::left:
                line.startX = 0;
                break;
            case RenderTextAlign::center:
                line.startX = maxLineWidth / 2.0f - lineWidth / 2.0f;
                break;
        }
    }
}

struct WordMarker
{
    const RenderGlyphRun* run;
    uint32_t index;

    bool next(Span<const RenderGlyphRun> runs)
    {
        index += 2;
        while (index >= run->breaks.size())
        {

            index -= run->breaks.size();
            run++;
            if (run == runs.end())
            {
                return false;
            }
        }
        return true;
    }
};

class RunIterator
{
    Span<const RenderGlyphRun> m_runs;
    const RenderGlyphRun* m_run;
    uint32_t m_index;

public:
    RunIterator(Span<const RenderGlyphRun> runs, const RenderGlyphRun* run, uint32_t index) :
        m_runs(runs), m_run(run), m_index(index)
    {}

    bool back()
    {
        if (m_index == 0)
        {
            if (m_run == m_runs.begin())
            {
                return false;
            }
            m_run--;
            if (m_run->glyphs.size() == 0)
            {
                m_index = 0;
                return back();
            }
            else
            {
                m_index = m_run->glyphs.size() == 0 ? 0 : (uint32_t)m_run->glyphs.size() - 1;
            }
        }
        else
        {
            m_index--;
        }
        return true;
    }

    bool forward()
    {
        if (m_index == m_run->glyphs.size())
        {
            if (m_run == m_runs.end())
            {
                return false;
            }
            m_run++;
            m_index = 0;
            if (m_index == m_run->glyphs.size())
            {
                return forward();
            }
        }
        else
        {
            m_index++;
        }
        return true;
    }

    float x() const { return m_run->xpos[m_index]; }

    const RenderGlyphRun* run() const { return m_run; }
    uint32_t index() const { return m_index; }

    bool operator==(const RunIterator& o) const { return m_run == o.m_run && m_index == o.m_index; }
};

std::vector<RenderGlyphLine> RenderGlyphLine::BreakLines(Span<const RenderGlyphRun> runs,
                                                         float width,
                                                         RenderTextAlign align)
{

    float maxLineWidth = autowidth(width) ? std::numeric_limits<float>::max() : width;

    std::vector<RenderGlyphLine> lines;

    if (runs.empty())
    {
        return lines;
    }

    auto limit = maxLineWidth;

    bool advanceWord = false;
    WordMarker start = {runs.begin(), 0};
    WordMarker end = {runs.begin(), 1};

    RenderGlyphLine line = RenderGlyphLine();

    uint32_t breakIndex = end.run->breaks[end.index];
    uint32_t lastEndIndex = end.index;
    uint32_t startBreakIndex = start.run->breaks[start.index];
    float x = end.run->xpos[breakIndex];
    while (true)
    {
        if (advanceWord)
        {
            lastEndIndex = end.index;

            if (!start.next(runs))
            {
                break;
            }
            if (!end.next(runs))
            {
                break;
            }

            advanceWord = false;

            breakIndex = end.run->breaks[end.index];
            startBreakIndex = start.run->breaks[start.index];
            x = end.run->xpos[breakIndex];
        }

        if (breakIndex != startBreakIndex && x > limit)
        {
            uint32_t startRun = (uint32_t)(start.run - runs.begin());

            // A whole word overflowed, break until we can no longer break (or
            // it fits).
            if (line.startRun == startRun && line.startIndex == startBreakIndex)
            {
                bool canBreakMore = true;
                while (canBreakMore && x > limit)
                {

                    RunIterator lineStart =
                        RunIterator(runs, runs.begin() + line.startRun, line.startIndex);
                    RunIterator lineEnd = RunIterator(runs, end.run, end.run->breaks[end.index]);

                    // Look for the next character that doesn't overflow.
                    while (true)
                    {
                        if (!lineEnd.back())
                        {
                            // Hit the start of the text, can't go back.
                            canBreakMore = false;
                            break;
                        }
                        else if (lineEnd.x() <= limit)
                        {
                            if (lineStart == lineEnd && !lineEnd.forward())
                            {
                                // Hit the start of the line and could not
                                // go forward to consume a single character.
                                // We can't break any further.
                                canBreakMore = false;
                            }
                            else
                            {
                                line.endRun = (uint32_t)(lineEnd.run() - runs.begin());
                                line.endIndex = lineEnd.index();
                            }
                            break;
                        }
                    }
                    if (canBreakMore)
                    {
                        // Add the line and push the limit out.
                        limit = lineEnd.x() + maxLineWidth;
                        if (!line.empty())
                        {
                            lines.push_back(line);
                        }
                        // Setup the next line.
                        line = RenderGlyphLine((uint32_t)(lineEnd.run() - runs.begin()),
                                               lineEnd.index());
                    }
                }
            }
            else
            {
                // word overflowed, knock it to a new line
                auto startX = start.run->xpos[start.run->breaks[start.index]];
                limit = startX + maxLineWidth;

                if (!line.empty() || start.index - lastEndIndex > 1)
                {
                    lines.push_back(line);
                }

                line = RenderGlyphLine(startRun, startBreakIndex);
            }
        }
        else
        {
            line.endRun = (uint32_t)(end.run - runs.begin());
            line.endIndex = end.run->breaks[end.index];
            advanceWord = true;
            // Forced BR.
            if (breakIndex == startBreakIndex)
            {
                lines.push_back(line);
                auto startX = start.run->xpos[start.run->breaks[start.index]];
                limit = startX + maxLineWidth;
                line = RenderGlyphLine((uint32_t)(start.run - runs.begin()), startBreakIndex + 1);
            }
        }
    }
    // Don't add a line that starts/ends at the same spot.
    if (!line.empty())
    {
        lines.push_back(line);
    }

    ComputeLineSpacing(lines, runs, width, align);
    return lines;
}