/*
 * 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
};

// 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);

    // 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;

    // 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;

    // 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;
    };

    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

        // 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;
};

// 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
                bool wantEllipsis,
                bool isEllipsisLineLast,
                GlyphRun* ellipsisRun,
                float y);

    bool 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; }
    float y() const { return m_y; }
    float bottom() 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_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
