/*
 * Copyright 2022 Rive
 */

#ifndef _RIVE_TEXT_HPP_
#define _RIVE_TEXT_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;

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

    // This is experimental
    // -- may only be needed by Editor
    // -- so it may be removed from here later
    //
    struct Axis
    {
        uint32_t tag;
        float min;
        float def; // default value
        float max;
    };

    // Returns the canonical set of Axes for this font. Use this to know
    // what variations are possible. If you want to know the specific
    // coordinate within that variations space for *this* font, call
    // getCoords().
    //
    virtual std::vector<Axis> getAxes() const = 0;

    struct Coord
    {
        uint32_t axis;
        float value;
    };

    // Returns the specific coords in variation space for this font.
    // If you want to have a description of the entire variation space,
    // call getAxes().
    //
    virtual std::vector<Coord> getCoords() const = 0;

    virtual rcp<Font> makeAtCoords(Span<const Coord>) const = 0;

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

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

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

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

private:
    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;
    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)
    {}

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

    rcp<Font> font;
    float size;

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

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