/*
 * Copyright 2022 Rive
 */

#ifndef _RIVE_TEXT_ENGINE_HPP_
#define _RIVE_TEXT_ENGINE_HPP_

#include "rive/math/raw_path.hpp"
#include "rive/refcnt.hpp"
#include "rive/shapes/paint/color.hpp"
#include "rive/span.hpp"
#include "rive/simple_array.hpp"

#include <vector>

namespace rive
{

enum class TextSizing : uint8_t
{
  autoWidth,
  autoHeight,
  fixed
};

enum class TextOverflow : uint8_t
{
  visible,
  hidden,
  clipped,
  ellipsis,
  fit,
  fitFontSize,
};

enum class TextOrigin : uint8_t
{
  top,
  baseline
};

// Top edge the vertical bounding box is trimmed to.
enum class TextTrimTop : uint8_t
{
  none = 0, // No trim: box top stays at the font ascent.
  cap = 1,  // Box top at the cap-height line.
  ex = 2,   // Box top at the x-height line.
};

// Bottom edge the vertical bounding box is trimmed to.
enum class TextTrimBottom : uint8_t
{
  none = 0,       // No trim: box bottom stays at the font descent.
  alphabetic = 1, // Box bottom at the baseline.
  text = 2,       // Box bottom at the text (natural descent) line.
};

// Text::verticalTrimValue packs an independent top and bottom trim edge so new
// edge types can be added later without introducing a new property. The top
// edge occupies the low byte and the bottom edge the next byte; the remaining
// bits (and the high 16) are reserved for future values.
constexpr uint32_t textTrimTopShift = 0;
constexpr uint32_t textTrimBottomShift = 8;
constexpr uint32_t textTrimFieldMask = 0xFF;

inline TextTrimTop textTrimTop(uint32_t packed)
{
  return (TextTrimTop)((packed >> textTrimTopShift) & textTrimFieldMask);
}
inline TextTrimBottom textTrimBottom(uint32_t packed)
{
  return (TextTrimBottom)((packed >> textTrimBottomShift) & textTrimFieldMask);
}
inline uint32_t packTextVerticalTrim(TextTrimTop top, TextTrimBottom bottom)
{
  return ((uint32_t)top << textTrimTopShift) |
         ((uint32_t)bottom << textTrimBottomShift);
}

// Representation of a single unicode codepoint.
using Unichar = uint32_t;
// Id for a glyph within a font.
using GlyphID = uint16_t;

struct TextRun;
struct GlyphRun;

bool isWhiteSpace(Unichar c);

// Direction a paragraph or run flows in.
enum class TextDirection : uint8_t
{
  ltr = 0,
  rtl = 1
};

// The alignment of each word wrapped line in a paragraph.
enum class TextAlign : uint8_t
{
  left = 0,
  right = 1,
  center = 2
};

// The wrap mode.
enum class TextWrap : uint8_t
{
  wrap = 0,
  noWrap = 1
};

// How a word that doesn't fit the line may be split. Mirrors the useful half
// of CSS overflow-wrap + word-break. breakWord is 0 so it stays the default
// for content authored before the property existed, and so an out of range
// value falls back to the historical behavior.
enum class TextWordBreak : uint8_t
{
  // overflow-wrap: break-word. Move the word to its own line and only cut
  // it when it still doesn't fit there.
  breakWord = 0,
  // overflow-wrap: normal. Never cut a word; one that doesn't fit even on a
  // line of its own overflows the box.
  normal = 1,
  // word-break: break-all. Cut at any cluster boundary so every line is
  // packed to the edge.
  breakAll = 2
};

// The alignment of each word wrapped line in a paragraph.
enum class VerticalTextAlign : uint8_t
{
  top = 0,
  bottom = 1,
  middle = 2
};

// A horizontal line of text within a paragraph, after line-breaking.
struct GlyphLine
{
  uint32_t startRunIndex;
  uint32_t startGlyphIndex;
  uint32_t endRunIndex;
  uint32_t endGlyphIndex;
  float startX;
  float top = 0, baseline = 0, bottom = 0;

  bool operator==(const GlyphLine& o) const
  {
    return startRunIndex == o.startRunIndex &&
           startGlyphIndex == o.startGlyphIndex &&
           endRunIndex == o.endRunIndex && endGlyphIndex == o.endGlyphIndex;
  }

  GlyphLine()
      : startRunIndex(0)
      , startGlyphIndex(0)
      , endRunIndex(0)
      , endGlyphIndex(0)
      , startX(0.0f)
  {}
  GlyphLine(uint32_t run, uint32_t index)
      : startRunIndex(run)
      , startGlyphIndex(index)
      , endRunIndex(run)
      , endGlyphIndex(index)
      , startX(0.0f)
  {}

  bool empty() const
  {
    return startRunIndex == endRunIndex && startGlyphIndex == endGlyphIndex;
  }

  static SimpleArray<GlyphLine> BreakLines(
      Span<const GlyphRun> runs,
      float width,
      TextWordBreak wordBreak = TextWordBreak::breakWord);

  // Compute values for top/baseline/bottom per line
  static void ComputeLineSpacing(
      bool isFirstLine,
      Span<GlyphLine>,
      Span<const GlyphRun>,
      float width,
      TextAlign align);

  static float ComputeMaxWidth(
      Span<GlyphLine> lines,
      Span<const GlyphRun> runs);
};

// A paragraph represents of set of runs that flow in a specific direction. The
// runs are always provided in LTR and must be drawn in reverse when the
// baseDirection is RTL. These are built by the system during shaping where the
// user provided string and text styling is converted to shaped paragraphs.
struct Paragraph
{
  SimpleArray<GlyphRun> runs;
  uint8_t level;
  TextDirection baseDirection() const
  {
    return level & 1 ? TextDirection::rtl : TextDirection::ltr;
  }
};

// An abstraction for interfacing with an individual font.
class Font : public RefCnt<Font>
{
public:
  virtual ~Font() {}

  struct LineMetrics
  {
    float ascent, descent;
    // Distances from the baseline to the top of capital / lowercase
    // letters, stored negative (up is -Y) like ascent. Both fall back to
    // ascent when the font does not provide the metric.
    float capHeight = 0.0f;
    float xHeight = 0.0f;
  };

  const LineMetrics& lineMetrics() const { return m_lineMetrics; }

  float ascent(float size) const { return m_lineMetrics.ascent * size; }

  float descent(float size) const { return m_lineMetrics.descent * size; }

  float capHeight(float size) const { return m_lineMetrics.capHeight * size; }

  float xHeight(float size) const { return m_lineMetrics.xHeight * size; }

  // Variable axis available for the font.
  struct Axis
  {
    uint32_t tag;
    float min;
    float def; // default value
    float max;
  };

  // Variable axis setting.
  struct Coord
  {
    uint32_t axis;
    float value;
  };

  // Returns the count of variable axes available for this font.
  virtual uint16_t getAxisCount() const = 0;

  // Returns the definition of the Axis at the provided index.
  virtual Axis getAxis(uint16_t index) const = 0;

  // Value for the axis, if a Coord has been provided the value from the Coord
  // will be used. Otherwise the default value for the axis will be returned.
  virtual float getAxisValue(uint32_t axisTag) const = 0;

  // Returns the current font value as a numeric value [1, 1000]
  virtual uint16_t getWeight() const = 0;

  // Whether this font is italic or not.
  virtual bool isItalic() const = 0;

  // Font feature.
  struct Feature
  {
    uint32_t tag;
    uint32_t value;
  };

  // Returns the features available for this font.
  virtual SimpleArray<uint32_t> features() const = 0;

  virtual bool hasGlyph(const rive::Unichar) const = 0;

  // Nominal Unicode scalar coverage in ascending order, without fallback.
  virtual std::vector<Unichar> codepoints() const = 0;

  // Value for the feature, if no value has been provided a (uint32_t)-1 is
  // returned to signal that the text engine will pick the best feature value
  // for the content.
  virtual uint32_t getFeatureValue(uint32_t featureTag) const = 0;

  rcp<Font> makeAtCoords(Span<const Coord> coords) const
  {
    return withOptions(coords, Span<const Feature>(nullptr, 0));
  }

  rcp<Font> makeAtCoord(Coord c)
  {
    return this->makeAtCoords(Span<const Coord>(&c, 1));
  }

  virtual rcp<Font> withOptions(
      Span<const Coord> variableAxes,
      Span<const Feature> features) const = 0;

  // Returns a 1-point path for this glyph. It will be positioned
  // relative to (0,0) with the typographic baseline at y = 0.
  //
  virtual RawPath getPath(GlyphID) const = 0;

  // The same path as getPath, lent instead of copied. It stays valid until
  // the next glyphPath or getPath on this font, either of which may replace
  // it, so use it before asking for another glyph.
  virtual const RawPath& glyphPath(GlyphID glyph) const
  {
    m_lentPath = getPath(glyph);
    return m_lentPath;
  }

  // Color glyph (emoji) support via COLR/CPAL tables.

  // A single layer of a color glyph, with its own path and fill.
  struct GradientStop
  {
    float offset;
    ColorInt color;
    bool isForeground = false;
  };

  enum class ColorGlyphPaintType : uint8_t
  {
    solid,
    linearGradient,
    radialGradient,
    sweepGradient,
    image,
  };

  struct ColorGlyphLayer
  {
    RawPath path;
    ColorGlyphPaintType paintType = ColorGlyphPaintType::solid;
    ColorInt color = 0xFF000000; // ARGB (for solid fills)
    bool useForeground = false;  // true if color should use text color

    // Gradient data (only valid when paintType != solid).
    std::vector<GradientStop> stops;
    // Linear gradient: (x0,y0) start, (x1,y1) end.
    // Radial gradient: (x0,y0,r0) inner circle, (x1,y1,r1) outer circle.
    // Sweep gradient: (x0,y0) center, startAngle, endAngle.
    float x0 = 0, y0 = 0, x1 = 0, y1 = 0;
    float r0 = 0, r1 = 0;               // radial
    float startAngle = 0, endAngle = 0; // sweep
    // Maps the unit circle onto the radial's outer circle in glyph space,
    // keeping its ellipse under uneven or skewed font transforms.
    Mat2D radialTransform;

    // Image data (only valid when paintType == image).
    // Raw encoded image bytes (e.g. PNG from SBIX/CBDT).
    std::vector<uint8_t> imageBytes;
    unsigned int imageWidth = 0, imageHeight = 0;
    // Glyph extents for positioning the image.
    float imageBearingX = 0, imageBearingY = 0;
    float imageExtentX = 0, imageExtentY = 0;
  };

  // Whether this font contains any COLR color glyphs.
  virtual bool hasColorGlyphs() const { return false; }

  // Whether a specific glyph has color layers.
  virtual bool isColorGlyph(GlyphID) const { return false; }

  // Decompose a color glyph into its colored layers. Returns the number
  // of layers written to `out`. If the glyph is not a color glyph,
  // returns 0.
  virtual size_t getColorLayers(
      GlyphID,
      std::vector<ColorGlyphLayer>& out,
      ColorInt foreground = 0xFF000000) const
  {
    (void)out;
    (void)foreground;
    return 0;
  }

  SimpleArray<Paragraph> shapeText(
      Span<const Unichar> text,
      Span<const TextRun> runs,
      int textDirectionFlag = -1) const;

  // If the platform can supply fallback font(s), set this function pointer.
  // It will be called with a span of unichars, and the platform attempts to
  // return a font that can draw (at least some of) them. If no font is
  // available just return nullptr.

  using FallbackProc = rive::rcp<rive::Font> (*)(
      const rive::Unichar missing,
      const uint32_t fallbackIndex,
      const rive::Font*);
  static FallbackProc gFallbackProc;
  static bool gFallbackProcEnabled;
  static constexpr unsigned kRegularWeight = 400;

protected:
  Font(const LineMetrics& lm) : m_lineMetrics(lm) {}

  virtual SimpleArray<Paragraph> onShapeText(
      Span<const Unichar> text,
      Span<const TextRun> runs,
      int textDirectionFlag) const = 0;

private:
  /// The font specified line metrics (automatic line metrics).
  const LineMetrics m_lineMetrics;
  /// What the default glyphPath lends.
  mutable RawPath m_lentPath;
};

// A user defined styling guide for a set of unicode codepoints within a larger
// text string.
struct TextRun
{
  rcp<Font> font;
  float size;
  float lineHeight;
  float letterSpacing;
  uint32_t unicharCount;
  uint32_t script;
  uint16_t styleId;
  uint8_t level;
};

// The corresponding system generated run for the user provided TextRuns.
// GlyphRuns may not match TextRuns if the system needs to split the run (for
// fallback fonts) or if codepoints get ligated/shaped to a single glyph.
struct GlyphRun
{
  GlyphRun(size_t glyphCount = 0)
      : glyphs(glyphCount)
      , textIndices(glyphCount)
      , advances(glyphCount)
      , xpos(glyphCount + 1)
      , offsets(glyphCount)
  {}

  GlyphRun(
      SimpleArray<GlyphID> glyphIds,
      SimpleArray<uint32_t> offsets,
      SimpleArray<float> ws,
      SimpleArray<float> xs,
      SimpleArray<rive::Vec2D> offs)
      : glyphs(glyphIds)
      , textIndices(offsets)
      , advances(ws)
      , xpos(xs)
      , offsets(offs)
  {}

  rcp<Font> font;
  float size;
  float lineHeight;
  float letterSpacing;

  // List of glyphs, represented by font specific glyph ids. Length is equal
  // to number of glyphs in the run.
  SimpleArray<GlyphID> glyphs;

  // Index in the unicode text array representing the text displayed in this
  // run. Because each glyph can be composed of multiple unicode values, this
  // index points to the first index in the unicode text. Length is equal to
  // number of glyphs in the run.
  SimpleArray<uint32_t> textIndices;

  // X position of each glyph in visual order (xpos is in logical/memory
  // order).
  SimpleArray<float> advances;

  // X position of each glyph, with an extra value at the end for the right
  // most extent of the last glyph.
  SimpleArray<float> xpos;

  // X and Y offset each glyphs draws at relative to its baseline and advance
  // position.
  SimpleArray<rive::Vec2D> offsets;

  // List of possible indices to line break at. Has a stride of 2 uint32_ts
  // where each pair marks the start and end of a word, with the exception of
  // a return character (forced linebreak) which is represented as a 0 length
  // word (where start/end index is the same).
  SimpleArray<uint32_t> breaks;

  // The unique identifier for the styling (fill/stroke colors, anything not
  // determined by the font or font size) applied to this run.
  uint16_t styleId;

  // Bidi level (even is LTR, odd is RTL)
  uint8_t level;

  // List of indices where words are joined by a word-joiner character.
  // During text breaking, these joins should be honored and not split at
  // those points
  SimpleArray<uint32_t> joiners;

  TextDirection dir() const
  {
    return level & 1 ? TextDirection::rtl : TextDirection::ltr;
  }
};

class OrderedLine;

// STL-style iterator for individual glyphs in a line, simplfies call sites from
// needing to iterate both runs and glyphs within those runs per line. A single
// iterator allows iterating all the glyphs in the line and provides the correct
// run they belong to (this also takes into account bidi which can put the runs
// in different order from how they were provided by the line breaker).
//
//   for (auto [run, glyphIndex] : orderedLine) { ... }
//
class GlyphItr
{
public:
  GlyphItr() = default;
  GlyphItr(
      const OrderedLine* line,
      const rive::GlyphRun* const* run,
      uint32_t glyphIndex)
      : m_line(line)
      , m_run(run)
      , m_glyphIndex(glyphIndex)
  {}

  void tryAdvanceRun();

  bool operator!=(const GlyphItr& that) const
  {
    return m_run != that.m_run || m_glyphIndex != that.m_glyphIndex;
  }
  bool operator==(const GlyphItr& that) const
  {
    return m_run == that.m_run && m_glyphIndex == that.m_glyphIndex;
  }

  GlyphItr& operator++();

  std::tuple<const GlyphRun*, uint32_t> operator*() const
  {
    return {*m_run, m_glyphIndex};
  }

  const rive::GlyphRun* run() const { return *m_run; }
  uint32_t glyphIndex() const { return m_glyphIndex; }

private:
  const OrderedLine* m_line;
  const rive::GlyphRun* const* m_run;
  uint32_t m_glyphIndex;
};

class GlyphLookup;
// Represents a line of text with runs ordered visually. Also tracks logical
// start/end which will differ when using bidi.
class OrderedLine
{
public:
  OrderedLine(
      const Paragraph& paragraph,
      const GlyphLine& line,
      float lineWidth, // for ellipsis
      TextAlign align, // re-aligns a line the ellipsis shortened
      bool wantEllipsis,
      bool isEllipsisLineLast,
      GlyphRun* ellipsisRun,
      float y);

  // Returns the width of the ellipsized line, or a negative value when the
  // line didn't need one.
  float buildEllipsisRuns(
      std::vector<const GlyphRun*>& logicalRuns,
      const Paragraph& paragraph,
      const GlyphLine& line,
      float lineWidth,
      bool isEllipsisLineLast,
      GlyphRun* ellipsisRun);
  const GlyphRun* startLogical() const { return m_startLogical; }
  const GlyphRun* endLogical() const { return m_endLogical; }
  const std::vector<const GlyphRun*>& runs() const { return m_runs; }

  GlyphItr begin() const
  {
    auto runItr = m_runs.data();
    auto itr = GlyphItr(this, runItr, startGlyphIndex(*runItr));
    itr.tryAdvanceRun();
    return itr;
  }

  GlyphItr end() const
  {
    auto runItr = m_runs.data() + (m_runs.size() == 0 ? 0 : m_runs.size() - 1);
    return GlyphItr(this, runItr, endGlyphIndex(*runItr));
  }

  const GlyphLine& glyphLine() const { return *m_glyphLine; }
  // Where the line's first visual glyph starts. Matches glyphLine().startX
  // unless an ellipsis changed the line's width.
  float startX() const { return m_startX; }
  float y() const { return m_y; }
  float bottom() const;

  // An empty line holds only the line break that ends it, which belongs to
  // no line.
  bool isEmpty() const { return !(begin() != end()); }
  // Where a cursor on an empty line sits: just before its line break. Found
  // by the break's own glyph, as iterating can't reach it: an empty right to
  // left line begins at the glyph before.
  bool emptyLineCodePointIndex(uint32_t& outIndex) const;

  uint32_t firstCodePointIndex(const GlyphLookup& glyphLookup) const;
  uint32_t lastCodePointIndex(const GlyphLookup& glyphLookup) const;
  bool containsCodePointIndex(
      const GlyphLookup& glyphLookup,
      uint32_t codePointIndex) const;

private:
  const GlyphRun* m_startLogical = nullptr;
  const GlyphRun* m_endLogical = nullptr;
  uint32_t m_startGlyphIndex;
  uint32_t m_endGlyphIndex;
  std::vector<const GlyphRun*> m_runs;
  const GlyphLine* m_glyphLine;
  float m_startX;
  float m_y;

public:
  const GlyphRun* lastRun() const { return m_runs.back(); }
  uint32_t startGlyphIndex(const GlyphRun* run) const
  {
    TextDirection dir = run->level & 1 ? TextDirection::rtl
                                       : TextDirection::ltr;
    switch (dir)
    {
      case TextDirection::ltr:
        return m_startLogical == run ? m_startGlyphIndex : 0;
      case TextDirection::rtl:
        return (m_endLogical == run ? m_endGlyphIndex
                                    : (uint32_t)run->glyphs.size()) -
               1;
    }
    RIVE_UNREACHABLE();
  }
  uint32_t endGlyphIndex(const GlyphRun* run) const
  {
    TextDirection dir = run->level & 1 ? TextDirection::rtl
                                       : TextDirection::ltr;
    switch (dir)
    {
      case TextDirection::ltr:
        return m_endLogical == run ? m_endGlyphIndex
                                   : (uint32_t)run->glyphs.size();
      case TextDirection::rtl:
        return (m_startLogical == run ? m_startGlyphIndex : 0) - 1;
    }
    RIVE_UNREACHABLE();
  }
};

} // namespace rive
#endif
