#include "rive/text_engine.hpp"
#include "rive/text/utf.hpp"
#include "rive/text/glyph_lookup.hpp"
#include "rive/text/line_break.hpp"
#include <cstring>
using namespace rive;

bool rive::isWhiteSpace(Unichar c)
{
  // Zs spaces, line and paragraph separators, NEL and zero width space.
  // The no-break spaces U+00A0, U+2007 and U+202F are deliberately not.
  return c <= ' ' || c == 0x0085 || c == 0x1680 ||
         (c >= 0x2000 && c <= 0x200B && c != 0x2007) || c == 0x2028 ||
         c == 0x2029 || c == 0x205F || c == 0x3000;
}

#ifdef WITH_RIVE_TEXT

static void appendUnicode(
    std::vector<rive::Unichar>& unichars,
    const char text[])
{
  const uint8_t* ptr = (const uint8_t*)text;
  const uint8_t* end = ptr + strlen(text);
  while (ptr < end)
  {
    unichars.push_back(rive::UTF::NextUTF8(&ptr, end));
  }
}

static void reverseRuns(const GlyphRun** runs, int count)
{
  int halfCount = count / 2;
  int finalIndex = count - 1;

  for (int index = 0; index < halfCount; index++)
  {
    int tieIndex = finalIndex - index;

    const GlyphRun* tempRun = runs[index];
    runs[index] = runs[tieIndex];
    runs[tieIndex] = tempRun;
  }
}

OrderedLine::OrderedLine(
    const Paragraph& paragraph,
    const GlyphLine& line,
    float lineWidth,
    TextAlign align,
    bool wantEllipsis,
    bool isEllipsisLineLast,
    GlyphRun* ellipsisRun,
    float y)
    : m_startGlyphIndex(line.startGlyphIndex)
    , m_endGlyphIndex(line.endGlyphIndex)
    , m_glyphLine(&line)
    , m_startX(line.startX)
    , m_y(y)
{
  std::vector<const GlyphRun*> logicalRuns;
  const SimpleArray<GlyphRun>& glyphRuns = paragraph.runs;

  float ellipsizedWidth = wantEllipsis ? buildEllipsisRuns(
                                             logicalRuns,
                                             paragraph,
                                             line,
                                             lineWidth,
                                             isEllipsisLineLast,
                                             ellipsisRun)
                                       : -1.0f;
  if (ellipsizedWidth >= 0.0f)
  {
    // The line breaker aligned the full line, which overflows the box when
    // it doesn't wrap. Shift by however much the ellipsis changed its width
    // so right and center aligned lines sit inside the box again.
    float fullWidth = glyphRuns[line.endRunIndex].xpos[line.endGlyphIndex] -
                      glyphRuns[line.startRunIndex].xpos[line.startGlyphIndex];
    switch (align)
    {
      case TextAlign::right:
        m_startX += fullWidth - ellipsizedWidth;
        break;
      case TextAlign::center:
        m_startX += (fullWidth - ellipsizedWidth) / 2.0f;
        break;
      case TextAlign::left:
        break;
    }
  }
  else
  {
    for (uint32_t i = line.startRunIndex; i < line.endRunIndex + 1; i++)
    {
      logicalRuns.push_back(&glyphRuns[i]);
    }

    if (!logicalRuns.empty())
    {
      m_startLogical = logicalRuns.front();
      m_endLogical = logicalRuns.back();
    }
  }

  uint8_t maxLevel = 0;
  for (auto run : logicalRuns)
  {
    if (run->level > maxLevel)
    {
      maxLevel = run->level;
    }
  }
  for (uint8_t newLevel = maxLevel; newLevel > 0; newLevel--)
  {
    for (int start = (int)(logicalRuns.size()) - 1; start >= 0; start--)
    {
      if (logicalRuns[start]->level >= newLevel)
      {
        int count = 1;
        for (; start > 0 && logicalRuns[start - 1]->level >= newLevel; start--)
        {
          count++;
        }
        reverseRuns(logicalRuns.data() + start, count);
      }
    }
  }

  m_runs = std::move(logicalRuns);
}

bool OrderedLine::emptyLineCodePointIndex(uint32_t& outIndex) const
{
  if (!isEmpty() || m_startLogical == nullptr ||
      m_startGlyphIndex >= m_startLogical->textIndices.size())
  {
    return false;
  }
  outIndex = m_startLogical->textIndices[m_startGlyphIndex];
  return true;
}

uint32_t OrderedLine::firstCodePointIndex(const GlyphLookup& glyphLookup) const
{
  uint32_t breakIndex;
  if (emptyLineCodePointIndex(breakIndex))
  {
    return std::min(breakIndex, glyphLookup.lastCodePointIndex() - 1);
  }
  GlyphItr index = begin();
  auto glyphIndex = index.glyphIndex();
  auto run = index.run();
  uint32_t firstCodePointIndex = run->textIndices[glyphIndex];
  if (run->dir() == TextDirection::rtl)
  {
    // If the final run is RTL we want to add the length of the final glyph
    // to get the actual last available codepoint in the line.
    firstCodePointIndex += glyphLookup.count(run->textIndices[glyphIndex]);
  }
  // Clamp ignoring last zero width space for editing.
  return std::min(firstCodePointIndex, glyphLookup.lastCodePointIndex() - 1);
}

uint32_t OrderedLine::lastCodePointIndex(const GlyphLookup& glyphLookup) const
{
  // Counting an empty line's break would run it into the start of the next
  // line.
  uint32_t breakIndex;
  if (emptyLineCodePointIndex(breakIndex))
  {
    return std::min(breakIndex, glyphLookup.lastCodePointIndex() - 1);
  }
  GlyphItr index = begin();
  GlyphItr lastIndex = index;

  while (index != end())
  {
    lastIndex = index;
    ++index;
  }

  auto glyphIndex = lastIndex.glyphIndex();
  auto run = lastIndex.run();

  uint32_t lastCodePointIndex = run->textIndices[glyphIndex];
  if (run->dir() == TextDirection::ltr)
  {
    lastCodePointIndex += glyphLookup.count(run->textIndices[glyphIndex]);
  }
  // Clamp ignoring last zero width space for editing.
  return std::min(lastCodePointIndex, glyphLookup.lastCodePointIndex() - 1);
}

bool OrderedLine::containsCodePointIndex(
    const GlyphLookup& glyphLookup,
    uint32_t codePointIndex) const
{
  return codePointIndex >= firstCodePointIndex(glyphLookup) &&
         codePointIndex <= lastCodePointIndex(glyphLookup);
}

void GlyphItr::tryAdvanceRun()
{
  while (true)
  {
    auto run = *m_run;
    if (m_glyphIndex == m_line->endGlyphIndex(run) && run != m_line->lastRun())
    {
      m_run++;
      m_glyphIndex = m_line->startGlyphIndex(*m_run);
    }
    else
    {
      break;
    }
  }
}
GlyphItr& GlyphItr::operator++()
{
  auto run = *m_run;
  m_glyphIndex += run->dir() == TextDirection::ltr ? 1 : -1;
  tryAdvanceRun();
  return *this;
}

float OrderedLine::buildEllipsisRuns(
    std::vector<const GlyphRun*>& logicalRuns,
    const Paragraph& paragraph,
    const GlyphLine& line,
    float lineWidth,
    bool isEllipsisLineLast,
    GlyphRun* storedEllipsisRun)
{
  float x = 0.0f;
  const SimpleArray<GlyphRun>& glyphRuns = paragraph.runs;
  uint32_t startGIndex = line.startGlyphIndex;
  // If it's the last line we can actually early out if the whole things fits,
  // so check that first with no extra shaping.
  if (isEllipsisLineLast)
  {
    bool fits = true;

    for (uint32_t i = line.startRunIndex; i < line.endRunIndex + 1; i++)
    {
      const GlyphRun& run = glyphRuns[i];
      uint32_t endGIndex = i == line.endRunIndex ? line.endGlyphIndex
                                                 : (uint32_t)run.glyphs.size();

      for (uint32_t j = startGIndex; j != endGIndex; j++)
      {
        x += run.advances[j];
        if (x > lineWidth)
        {
          fits = false;
          goto measured;
        }
      }
      startGIndex = 0;
    }
  measured:
    if (fits)
    {
      // It fits, just get the regular glyphs.
      return -1.0f;
    }
  }

  std::vector<Unichar> ellipsisCodePoints;
  appendUnicode(ellipsisCodePoints, "...");

  rcp<Font> ellipsisFont = nullptr;
  float ellipsisFontSize = 0.0f;

  GlyphRun ellipsisRun = {};
  float ellipsisWidth = 0.0f;

  bool ellipsisOverflowed = false;
  startGIndex = line.startGlyphIndex;
  x = 0.0f;

  for (uint32_t i = line.startRunIndex; i < line.endRunIndex + 1; i++)
  {
    const GlyphRun& run = glyphRuns[i];
    if (run.font != ellipsisFont || run.size != ellipsisFontSize)
    {
      // Track the latest we've checked (even if we discard it so we don't
      // try to do this again for this ellipsis).
      ellipsisFont = run.font;
      ellipsisFontSize = run.size;

      // Get the next shape so we can check if it fits, otherwise keep
      // using the last one.
      TextRun ellipsisRuns[] = {{
          ellipsisFont,
          ellipsisFontSize,
          run.lineHeight,
          run.letterSpacing,
          (uint32_t)ellipsisCodePoints.size(),
          0, // default, TextRun.script
          run.styleId,
      }};
      // Shape in the paragraph's direction so the ellipsis resolves to the
      // paragraph's level and reorders to its end edge (the left of a right
      // to left paragraph), instead of always flowing left to right.
      auto nextEllipsisShape = ellipsisFont->shapeText(
          ellipsisCodePoints,
          Span<TextRun>(ellipsisRuns, 1),
          paragraph.level & 1);

      // Hard assumption one run and para
      const Paragraph& para = nextEllipsisShape[0];
      const GlyphRun& nextEllipsisRun = para.runs.front();

      float nextEllipsisWidth = 0;
      for (size_t j = 0; j < nextEllipsisRun.glyphs.size(); j++)
      {
        nextEllipsisWidth += nextEllipsisRun.advances[j];
      }

      if (ellipsisRun.font == nullptr || x + nextEllipsisWidth <= lineWidth)
      {
        // This ellipsis still fits, go ahead and use it. Otherwise
        // stick with the old one.
        ellipsisWidth = nextEllipsisWidth;
        ellipsisRun = std::move(para.runs.front());
      }
    }

    uint32_t endGIndex = i == line.endRunIndex ? line.endGlyphIndex
                                               : (uint32_t)run.glyphs.size();
    for (uint32_t j = startGIndex; j != endGIndex; j++)
    {
      float advance = run.advances[j];
      if (x + advance + ellipsisWidth > lineWidth)
      {
        m_endGlyphIndex = j;
        ellipsisOverflowed = true;
        break;
      }
      x += advance;
    }
    startGIndex = 0;
    logicalRuns.push_back(&run);
    m_endLogical = &run;

    if (ellipsisOverflowed && ellipsisRun.font != nullptr)
    {
      *storedEllipsisRun = std::move(ellipsisRun);
      logicalRuns.push_back(storedEllipsisRun);
      break;
    }
  }

  // There was enough space for it, so let's add the ellipsis (if we didn't
  // already). Note that we already checked if this is the last line and found
  // that the whole text didn't fit.
  if (!ellipsisOverflowed && ellipsisRun.font != nullptr)
  {
    *storedEllipsisRun = std::move(ellipsisRun);
    logicalRuns.push_back(storedEllipsisRun);
  }
  m_startLogical = storedEllipsisRun == logicalRuns.front()
                       ? nullptr
                       : logicalRuns.front();
  return x + ellipsisWidth;
}

float OrderedLine::bottom() const
{
  return m_y - m_glyphLine->baseline + m_glyphLine->bottom;
}

SimpleArray<Paragraph> Font::shapeText(
    Span<const Unichar> text,
    Span<const TextRun> runs,
    int textDirectionFlag) const
{
#ifdef DEBUG
  size_t count = 0;
  for (const TextRun& tr : runs)
  {
    assert(tr.unicharCount > 0);
    count += tr.unicharCount;
  }
  assert(count <= text.size());
#endif

  SimpleArray<Paragraph> paragraphs = onShapeText(
      text,
      runs,
      textDirectionFlag);
  // Boundaries live on the stack for typical UI strings.
  constexpr size_t kInlineBreaks = 257;
  LineBreak inlineBreaks[kInlineBreaks];
  std::vector<LineBreak> heapBreaks;
  size_t breakCount = text.size() + 1;
  if (breakCount > kInlineBreaks)
  {
    heapBreaks.resize(breakCount);
  }
  Span<LineBreak> lineBreaks(
      heapBreaks.empty() ? inlineBreaks : heapBreaks.data(),
      breakCount);
  computeLineBreaks(text, lineBreaks);
  bool inWord = false;
  GlyphRun* lastRun = nullptr;
  size_t reserveSize = text.size() / 4;
  SimpleArrayBuilder<uint32_t> breakBuilder(reserveSize);
  SimpleArrayBuilder<uint32_t> joinerBuilder(reserveSize);
  for (const Paragraph& para : paragraphs)
  {
    for (GlyphRun& gr : para.runs)
    {
      if (lastRun != nullptr)
      {
        lastRun->breaks = std::move(breakBuilder);
        lastRun->joiners = std::move(joinerBuilder);
        // Reset the builder.
        breakBuilder = SimpleArrayBuilder<uint32_t>(reserveSize);
        joinerBuilder = SimpleArrayBuilder<uint32_t>(reserveSize);
      }
      uint32_t glyphIndex = 0;
      uint32_t lastOffset = (uint32_t)-1;
      for (uint32_t offset : gr.textIndices)
      {
        // Only the first glyph of a cluster can start or end a word.
        if (offset == lastOffset)
        {
          glyphIndex++;
          continue;
        }
        lastOffset = offset;
        Unichar unicode = text[offset];
        if (lineBreaks[offset + 1] == LineBreak::mandatory)
        {
          breakBuilder.add(glyphIndex);
          breakBuilder.add(glyphIndex);
        }
        // Only U+2060 and U+FEFF are word joiners, skip the lookup
        // for everything below them.
        if (unicode >= 0x2060 &&
            lineBreakProps(unicode).cls == LineBreakClass::WJ)
        {
          joinerBuilder.add(offset);
        }
        if (inWord)
        {
          if (isWhiteSpace(unicode))
          {
            breakBuilder.add(glyphIndex);
            inWord = false;
          }
          // Soft hyphens stay unbreakable until we can draw the
          // hyphen at the line end.
          else if (
              lineBreaks[offset] == LineBreak::allowed &&
              text[offset - 1] != 0x00AD)
          {
            breakBuilder.add(glyphIndex);
            breakBuilder.add(glyphIndex);
          }
        }
        else if (!isWhiteSpace(unicode))
        {
          breakBuilder.add(glyphIndex);
          inWord = true;
        }
        glyphIndex++;
      }

      lastRun = &gr;
    }
  }
  if (lastRun != nullptr)
  {
    if (inWord)
    {
      breakBuilder.add((uint32_t)lastRun->glyphs.size());
    }
    else
    {
      // Consume the rest of the run.
      breakBuilder.add(breakBuilder.empty() ? 0 : breakBuilder.back());
      breakBuilder.add((uint32_t)lastRun->glyphs.size());
    }
    lastRun->breaks = std::move(breakBuilder);
    lastRun->joiners = std::move(joinerBuilder);
  }

#ifdef DEBUG
  for (const Paragraph& para : paragraphs)
  {
    for (const GlyphRun& gr : para.runs)
    {
      assert(gr.glyphs.size() > 0);
      assert(gr.glyphs.size() == gr.textIndices.size());
      assert(gr.glyphs.size() + 1 == gr.xpos.size());
    }
  }
#endif
  return paragraphs;
}
#endif
