// 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/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 { return fForeground; }
    void setForegroundColor(SkPaint paint) {
        fHasForeground = true;
        fForeground = std::move(paint);
    }
    void clearForegroundColor() { fHasForeground = false; }

    bool hasBackground() const { return fHasBackground; }
    SkPaint getBackground() const { return fBackground; }
    void setBackgroundColor(SkPaint paint) {
        fHasBackground = true;
        fBackground = std::move(paint);
    }
    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;
    SkPaint fBackground;
    bool fHasForeground = false;
    SkPaint 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
