/*
 * 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/span.hpp"
#include "rive/simple_array.hpp"

namespace rive
{

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

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

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

    struct LineMetrics
    {
        float ascent, descent;
    };

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

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

    // 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(rive::Span<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;

    SimpleArray<Paragraph> shapeText(Span<const Unichar> text, Span<const TextRun> runs) 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> (*)(rive::Span<const rive::Unichar>);
    static FallbackProc gFallbackProc;
    static bool gFallbackProcEnabled;

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

    virtual SimpleArray<Paragraph> onShapeText(Span<const Unichar> text,
                                               Span<const TextRun> runs) 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;
    TextDirection dir;
};

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

    // The text direction (LTR = 0/RTL = 1)
    TextDirection dir;
};

} // namespace rive
#endif
