// Copyright 2019 Google LLC.
#ifndef TextStyle_DEFINED
#define TextStyle_DEFINED

#include <optional>
#include <vector>
#include "include/core/SkColor.h"
#include "include/core/SkFont.h"
#include "include/core/SkFontMetrics.h"
#include "include/core/SkFontStyle.h"
#include "include/core/SkPaint.h"
#include "include/core/SkScalar.h"
#include "modules/skparagraph/include/DartTypes.h"
#include "modules/skparagraph/include/FontArguments.h"
#include "modules/skparagraph/include/ParagraphPainter.h"
#include "modules/skparagraph/include/TextShadow.h"

// TODO: Make it external so the other platforms (Android) could use it
#define DEFAULT_FONT_FAMILY "sans-serif"

namespace skia {
namespace textlayout {

static inline bool nearlyZero(SkScalar x, SkScalar tolerance = SK_ScalarNearlyZero) {
    if (SkScalarIsFinite(x)) {
        return SkScalarNearlyZero(x, tolerance);
    }
    return false;
}

static inline bool nearlyEqual(SkScalar x, SkScalar y, SkScalar tolerance = SK_ScalarNearlyZero) {
    if (SkScalarIsFinite(x) && SkScalarIsFinite(x)) {
        return SkScalarNearlyEqual(x, y, tolerance);
    }
    // Inf == Inf, anything else is false
    return x == y;
}

// Multiple decorations can be applied at once. Ex: Underline and overline is
// (0x1 | 0x2)
enum TextDecoration {
    kNoDecoration = 0x0,
    kUnderline = 0x1,
    kOverline = 0x2,
    kLineThrough = 0x4,
};
constexpr TextDecoration AllTextDecorations[] = {
        kNoDecoration,
        kUnderline,
        kOverline,
        kLineThrough,
};

enum TextDecorationStyle { kSolid, kDouble, kDotted, kDashed, kWavy };

enum TextDecorationMode { kGaps, kThrough };

enum StyleType {
    kNone,
    kAllAttributes,
    kFont,
    kForeground,
    kBackground,
    kShadow,
    kDecorations,
    kLetterSpacing,
    kWordSpacing
};

struct Decoration {
    TextDecoration fType;
    TextDecorationMode fMode;
    SkColor fColor;
    TextDecorationStyle fStyle;
    SkScalar fThicknessMultiplier;

    bool operator==(const Decoration& other) const {
        return this->fType == other.fType &&
               this->fMode == other.fMode &&
               this->fColor == other.fColor &&
               this->fStyle == other.fStyle &&
               this->fThicknessMultiplier == other.fThicknessMultiplier;
    }
};

/// Where to vertically align the placeholder relative to the surrounding text.
enum class PlaceholderAlignment {
  /// Match the baseline of the placeholder with the baseline.
  kBaseline,

  /// Align the bottom edge of the placeholder with the baseline such that the
  /// placeholder sits on top of the baseline.
  kAboveBaseline,

  /// Align the top edge of the placeholder with the baseline specified in
  /// such that the placeholder hangs below the baseline.
  kBelowBaseline,

  /// Align the top edge of the placeholder with the top edge of the font.
  /// When the placeholder is very tall, the extra space will hang from
  /// the top and extend through the bottom of the line.
  kTop,

  /// Align the bottom edge of the placeholder with the top edge of the font.
  /// When the placeholder is very tall, the extra space will rise from
  /// the bottom and extend through the top of the line.
  kBottom,

  /// Align the middle of the placeholder with the middle of the text. When the
  /// placeholder is very tall, the extra space will grow equally from
  /// the top and bottom of the line.
  kMiddle,
};

struct FontFeature {
    FontFeature(const SkString name, int value) : fName(name), fValue(value) {}
    bool operator==(const FontFeature& that) const {
        return fName == that.fName && fValue == that.fValue;
    }
    SkString fName;
    int fValue;
};

struct PlaceholderStyle {
    PlaceholderStyle() = default;
    PlaceholderStyle(SkScalar width, SkScalar height, PlaceholderAlignment alignment,
                     TextBaseline baseline, SkScalar offset)
            : fWidth(width)
            , fHeight(height)
            , fAlignment(alignment)
            , fBaseline(baseline)
            , fBaselineOffset(offset) {}

    bool equals(const PlaceholderStyle&) const;

    SkScalar fWidth = 0;
    SkScalar fHeight = 0;
    PlaceholderAlignment fAlignment = PlaceholderAlignment::kBaseline;
    TextBaseline fBaseline = TextBaseline::kAlphabetic;
    // Distance from the top edge of the rect to the baseline position. This
    // baseline will be aligned against the alphabetic baseline of the surrounding
    // text.
    //
    // Positive values drop the baseline lower (positions the rect higher) and
    // small or negative values will cause the rect to be positioned underneath
    // the line. When baseline == height, the bottom edge of the rect will rest on
    // the alphabetic baseline.
    SkScalar fBaselineOffset = 0;
};

class TextStyle {
public:
    TextStyle() = default;
    TextStyle(const TextStyle& other) = default;
    TextStyle& operator=(const TextStyle& other) = default;

    TextStyle cloneForPlaceholder();

    bool equals(const TextStyle& other) const;
    bool equalsByFonts(const TextStyle& that) const;
    bool matchOneAttribute(StyleType styleType, const TextStyle& other) const;
    bool operator==(const TextStyle& rhs) const { return this->equals(rhs); }

    // Colors
    SkColor getColor() const { return fColor; }
    void setColor(SkColor color) { fColor = color; }

    bool hasForeground() const { return fHasForeground; }
    SkPaint getForeground() const {
        const SkPaint* paint = std::get_if<SkPaint>(&fForeground);
        return paint ? *paint : SkPaint();
    }
    ParagraphPainter::SkPaintOrID getForegroundPaintOrID() const {
        return fForeground;
    }
    void setForegroundPaint(SkPaint paint) {
        fHasForeground = true;
        fForeground = std::move(paint);
    }
    // DEPRECATED: prefer `setForegroundPaint`.
    void setForegroundColor(SkPaint paint) { setForegroundPaint(paint); }
    // Set the foreground to a paint ID.  This is intended for use by clients
    // that implement a custom ParagraphPainter that can not accept an SkPaint.
    void setForegroundPaintID(ParagraphPainter::PaintID paintID) {
        fHasForeground = true;
        fForeground = paintID;
    }
    void clearForegroundColor() { fHasForeground = false; }

    bool hasBackground() const { return fHasBackground; }
    SkPaint getBackground() const {
        const SkPaint* paint = std::get_if<SkPaint>(&fBackground);
        return paint ? *paint : SkPaint();
    }
    ParagraphPainter::SkPaintOrID getBackgroundPaintOrID() const {
        return fBackground;
    }
    void setBackgroundPaint(SkPaint paint) {
        fHasBackground = true;
        fBackground = std::move(paint);
    }
    // DEPRECATED: prefer `setBackgroundPaint`.
    void setBackgroundColor(SkPaint paint) { setBackgroundPaint(paint); }
    void setBackgroundPaintID(ParagraphPainter::PaintID paintID) {
        fHasBackground = true;
        fBackground = paintID;
    }
    void clearBackgroundColor() { fHasBackground = false; }

    // Decorations
    Decoration getDecoration() const { return fDecoration; }
    TextDecoration getDecorationType() const { return fDecoration.fType; }
    TextDecorationMode getDecorationMode() const { return fDecoration.fMode; }
    SkColor getDecorationColor() const { return fDecoration.fColor; }
    TextDecorationStyle getDecorationStyle() const { return fDecoration.fStyle; }
    SkScalar getDecorationThicknessMultiplier() const {
        return fDecoration.fThicknessMultiplier;
    }
    void setDecoration(TextDecoration decoration) { fDecoration.fType = decoration; }
    void setDecorationMode(TextDecorationMode mode) { fDecoration.fMode = mode; }
    void setDecorationStyle(TextDecorationStyle style) { fDecoration.fStyle = style; }
    void setDecorationColor(SkColor color) { fDecoration.fColor = color; }
    void setDecorationThicknessMultiplier(SkScalar m) { fDecoration.fThicknessMultiplier = m; }

    // Weight/Width/Slant
    SkFontStyle getFontStyle() const { return fFontStyle; }
    void setFontStyle(SkFontStyle fontStyle) { fFontStyle = fontStyle; }

    // Shadows
    size_t getShadowNumber() const { return fTextShadows.size(); }
    std::vector<TextShadow> getShadows() const { return fTextShadows; }
    void addShadow(TextShadow shadow) { fTextShadows.emplace_back(shadow); }
    void resetShadows() { fTextShadows.clear(); }

    // Font features
    size_t getFontFeatureNumber() const { return fFontFeatures.size(); }
    std::vector<FontFeature> getFontFeatures() const { return fFontFeatures; }
    void addFontFeature(const SkString& fontFeature, int value)
        { fFontFeatures.emplace_back(fontFeature, value); }
    void resetFontFeatures() { fFontFeatures.clear(); }

    // Font arguments
    const std::optional<FontArguments>& getFontArguments() const { return fFontArguments; }
    // The contents of the SkFontArguments will be copied into the TextStyle,
    // and the SkFontArguments can be safely deleted after setFontArguments returns.
    void setFontArguments(const std::optional<SkFontArguments>& args);

    SkScalar getFontSize() const { return fFontSize; }
    void setFontSize(SkScalar size) { fFontSize = size; }

    const std::vector<SkString>& getFontFamilies() const { return fFontFamilies; }
    void setFontFamilies(std::vector<SkString> families) {
        fFontFamilies = std::move(families);
    }

    SkScalar getBaselineShift() const { return fBaselineShift; }
    void setBaselineShift(SkScalar baselineShift) { fBaselineShift = baselineShift; }

    void setHeight(SkScalar height) { fHeight = height; }
    SkScalar getHeight() const { return fHeightOverride ? fHeight : 0; }

    void setHeightOverride(bool heightOverride) { fHeightOverride = heightOverride; }
    bool getHeightOverride() const { return fHeightOverride; }

    void setHalfLeading(bool halfLeading) { fHalfLeading = halfLeading; }
    bool getHalfLeading() const { return fHalfLeading; }

    void setLetterSpacing(SkScalar letterSpacing) { fLetterSpacing = letterSpacing; }
    SkScalar getLetterSpacing() const { return fLetterSpacing; }

    void setWordSpacing(SkScalar wordSpacing) { fWordSpacing = wordSpacing; }
    SkScalar getWordSpacing() const { return fWordSpacing; }

    SkTypeface* getTypeface() const { return fTypeface.get(); }
    sk_sp<SkTypeface> refTypeface() const { return fTypeface; }
    void setTypeface(sk_sp<SkTypeface> typeface) { fTypeface = std::move(typeface); }

    SkString getLocale() const { return fLocale; }
    void setLocale(const SkString& locale) { fLocale = locale; }

    TextBaseline getTextBaseline() const { return fTextBaseline; }
    void setTextBaseline(TextBaseline baseline) { fTextBaseline = baseline; }

    void getFontMetrics(SkFontMetrics* metrics) const;

    bool isPlaceholder() const { return fIsPlaceholder; }
    void setPlaceholder() { fIsPlaceholder = true; }

private:
    static const std::vector<SkString>* kDefaultFontFamilies;

    Decoration fDecoration = {
            TextDecoration::kNoDecoration,
            // TODO: switch back to kGaps when (if) switching flutter to skparagraph
            TextDecorationMode::kThrough,
            // It does not make sense to draw a transparent object, so we use this as a default
            // value to indicate no decoration color was set.
            SK_ColorTRANSPARENT, TextDecorationStyle::kSolid,
            // Thickness is applied as a multiplier to the default thickness of the font.
            1.0f};

    SkFontStyle fFontStyle;

    std::vector<SkString> fFontFamilies = *kDefaultFontFamilies;

    SkScalar fFontSize = 14.0;
    SkScalar fHeight = 1.0;
    bool fHeightOverride = false;
    SkScalar fBaselineShift = 0.0f;
    // true: half leading.
    // false: scale ascent/descent with fHeight.
    bool fHalfLeading = false;
    SkString fLocale = {};
    SkScalar fLetterSpacing = 0.0;
    SkScalar fWordSpacing = 0.0;

    TextBaseline fTextBaseline = TextBaseline::kAlphabetic;

    SkColor fColor = SK_ColorWHITE;
    bool fHasBackground = false;
    ParagraphPainter::SkPaintOrID fBackground;
    bool fHasForeground = false;
    ParagraphPainter::SkPaintOrID fForeground;

    std::vector<TextShadow> fTextShadows;

    sk_sp<SkTypeface> fTypeface;
    bool fIsPlaceholder = false;

    std::vector<FontFeature> fFontFeatures;

    std::optional<FontArguments> fFontArguments;
};

typedef size_t TextIndex;
typedef SkRange<size_t> TextRange;
const SkRange<size_t> EMPTY_TEXT = EMPTY_RANGE;

struct Block {
    Block() = default;
    Block(size_t start, size_t end, const TextStyle& style) : fRange(start, end), fStyle(style) {}
    Block(TextRange textRange, const TextStyle& style) : fRange(textRange), fStyle(style) {}

    void add(TextRange tail) {
        SkASSERT(fRange.end == tail.start);
        fRange = TextRange(fRange.start, fRange.start + fRange.width() + tail.width());
    }

    TextRange fRange = EMPTY_RANGE;
    TextStyle fStyle;
};


typedef size_t BlockIndex;
typedef SkRange<size_t> BlockRange;
const size_t EMPTY_BLOCK = EMPTY_INDEX;
const SkRange<size_t> EMPTY_BLOCKS = EMPTY_RANGE;

struct Placeholder {
    Placeholder() = default;
    Placeholder(size_t start, size_t end, const PlaceholderStyle& style, const TextStyle& textStyle,
                BlockRange blocksBefore, TextRange textBefore)
            : fRange(start, end)
            , fStyle(style)
            , fTextStyle(textStyle)
            , fBlocksBefore(blocksBefore)
            , fTextBefore(textBefore) {}

    TextRange fRange = EMPTY_RANGE;
    PlaceholderStyle fStyle;
    TextStyle fTextStyle;
    BlockRange fBlocksBefore;
    TextRange fTextBefore;
};

}  // namespace textlayout
}  // namespace skia

#endif  // TextStyle_DEFINED
