/*
 * Copyright 2019 Google Inc.
 *
 * Use of this source code is governed by a BSD-style license that can be
 * found in the LICENSE file.
 */

#include "modules/skottie/src/text/TextAdapter.h"

#include "include/core/SkFontMgr.h"
#include "include/core/SkM44.h"
#include "include/private/SkTPin.h"
#include "modules/skottie/src/SkottieJson.h"
#include "modules/skottie/src/text/RangeSelector.h"
#include "modules/skottie/src/text/TextAnimator.h"
#include "modules/sksg/include/SkSGDraw.h"
#include "modules/sksg/include/SkSGGroup.h"
#include "modules/sksg/include/SkSGPaint.h"
#include "modules/sksg/include/SkSGRect.h"
#include "modules/sksg/include/SkSGRenderEffect.h"
#include "modules/sksg/include/SkSGText.h"
#include "modules/sksg/include/SkSGTransform.h"

namespace skottie {
namespace internal {

sk_sp<TextAdapter> TextAdapter::Make(const skjson::ObjectValue& jlayer,
                                     const AnimationBuilder* abuilder,
                                     sk_sp<SkFontMgr> fontmgr, sk_sp<Logger> logger) {
    // General text node format:
    // "t": {
    //    "a": [], // animators (see TextAnimator)
    //    "d": {
    //        "k": [
    //            {
    //                "s": {
    //                    "f": "Roboto-Regular",
    //                    "fc": [
    //                        0.42,
    //                        0.15,
    //                        0.15
    //                    ],
    //                    "j": 1,
    //                    "lh": 60,
    //                    "ls": 0,
    //                    "s": 50,
    //                    "t": "text align right",
    //                    "tr": 0
    //                },
    //                "t": 0
    //            }
    //        ]
    //    },
    //    "m": { // "more options"
    //           "g": 1,     // Anchor Point Grouping
    //           "a": {...}  // Grouping Alignment
    //         },
    //    "p": {}  // "path options" (TODO)
    // },

    const skjson::ObjectValue* jt = jlayer["t"];
    const skjson::ObjectValue* jd = jt ? static_cast<const skjson::ObjectValue*>((*jt)["d"])
                                       : nullptr;
    if (!jd) {
        abuilder->log(Logger::Level::kError, &jlayer, "Invalid text layer.");
        return nullptr;
    }

    // "More options"
    const skjson::ObjectValue* jm = (*jt)["m"];
    static constexpr AnchorPointGrouping gGroupingMap[] = {
        AnchorPointGrouping::kCharacter, // 'g': 1
        AnchorPointGrouping::kWord,      // 'g': 2
        AnchorPointGrouping::kLine,      // 'g': 3
        AnchorPointGrouping::kAll,       // 'g': 4
    };
    const auto apg = jm
            ? SkTPin<int>(ParseDefault<int>((*jm)["g"], 1), 1, SK_ARRAY_COUNT(gGroupingMap))
            : 1;

    auto adapter = sk_sp<TextAdapter>(new TextAdapter(std::move(fontmgr),
                                                      std::move(logger),
                                                      gGroupingMap[SkToSizeT(apg - 1)]));

    adapter->bind(*abuilder, jd, adapter->fText.fCurrentValue);
    if (jm) {
        adapter->bind(*abuilder, (*jm)["a"], adapter->fGroupingAlignment);
    }

    // Animators
    if (const skjson::ArrayValue* janimators = (*jt)["a"]) {
        adapter->fAnimators.reserve(janimators->size());

        for (const skjson::ObjectValue* janimator : *janimators) {
            if (auto animator = TextAnimator::Make(janimator, abuilder, adapter.get())) {
                adapter->fHasBlurAnimator     |= animator->hasBlur();
                adapter->fRequiresAnchorPoint |= animator->requiresAnchorPoint();

                adapter->fAnimators.push_back(std::move(animator));
            }
        }
    }

    abuilder->dispatchTextProperty(adapter);

    return adapter;
}

TextAdapter::TextAdapter(sk_sp<SkFontMgr> fontmgr, sk_sp<Logger> logger, AnchorPointGrouping apg)
    : fRoot(sksg::Group::Make())
    , fFontMgr(std::move(fontmgr))
    , fLogger(std::move(logger))
    , fAnchorPointGrouping(apg)
    , fHasBlurAnimator(false)
    , fRequiresAnchorPoint(false) {}

TextAdapter::~TextAdapter() = default;

void TextAdapter::addFragment(const Shaper::Fragment& frag) {
    // For a given shaped fragment, build a corresponding SG fragment:
    //
    //   [TransformEffect] -> [Transform]
    //     [Group]
    //       [Draw] -> [TextBlob*] [FillPaint]
    //       [Draw] -> [TextBlob*] [StrokePaint]
    //
    // * where the blob node is shared

    auto blob_node = sksg::TextBlob::Make(frag.fBlob);

    FragmentRec rec;
    rec.fOrigin     = frag.fPos;
    rec.fAdvance    = frag.fAdvance;
    rec.fAscent     = frag.fAscent;
    rec.fMatrixNode = sksg::Matrix<SkM44>::Make(SkM44::Translate(frag.fPos.x(), frag.fPos.y()));

    std::vector<sk_sp<sksg::RenderNode>> draws;
    draws.reserve(static_cast<size_t>(fText->fHasFill) + static_cast<size_t>(fText->fHasStroke));

    SkASSERT(fText->fHasFill || fText->fHasStroke);

    auto add_fill = [&]() {
        if (fText->fHasFill) {
            rec.fFillColorNode = sksg::Color::Make(fText->fFillColor);
            rec.fFillColorNode->setAntiAlias(true);
            draws.push_back(sksg::Draw::Make(blob_node, rec.fFillColorNode));
        }
    };
    auto add_stroke = [&] {
        if (fText->fHasStroke) {
            rec.fStrokeColorNode = sksg::Color::Make(fText->fStrokeColor);
            rec.fStrokeColorNode->setAntiAlias(true);
            rec.fStrokeColorNode->setStyle(SkPaint::kStroke_Style);
            rec.fStrokeColorNode->setStrokeWidth(fText->fStrokeWidth);
            draws.push_back(sksg::Draw::Make(blob_node, rec.fStrokeColorNode));
        }
    };

    if (fText->fPaintOrder == TextPaintOrder::kFillStroke) {
        add_fill();
        add_stroke();
    } else {
        add_stroke();
        add_fill();
    }

    SkASSERT(!draws.empty());

    if (0) {
        // enable to visualize fragment ascent boxes
        auto box_color = sksg::Color::Make(0xff0000ff);
        box_color->setStyle(SkPaint::kStroke_Style);
        box_color->setStrokeWidth(1);
        box_color->setAntiAlias(true);
        auto box = SkRect::MakeLTRB(0, rec.fAscent, rec.fAdvance, 0);
        draws.push_back(sksg::Draw::Make(sksg::Rect::Make(box), std::move(box_color)));
    }

    auto draws_node = (draws.size() > 1)
            ? sksg::Group::Make(std::move(draws))
            : std::move(draws[0]);

    if (fHasBlurAnimator) {
        // Optional blur effect.
        rec.fBlur = sksg::BlurImageFilter::Make();
        draws_node = sksg::ImageFilterEffect::Make(std::move(draws_node), rec.fBlur);
    }

    fRoot->addChild(sksg::TransformEffect::Make(std::move(draws_node), rec.fMatrixNode));
    fFragments.push_back(std::move(rec));
}

void TextAdapter::buildDomainMaps(const Shaper::Result& shape_result) {
    fMaps.fNonWhitespaceMap.clear();
    fMaps.fWordsMap.clear();
    fMaps.fLinesMap.clear();

    size_t i          = 0,
           line       = 0,
           line_start = 0,
           word_start = 0;

    float word_advance = 0,
          word_ascent  = 0,
          line_advance = 0,
          line_ascent  = 0;

    bool in_word = false;

    // TODO: use ICU for building the word map?
    for (; i  < shape_result.fFragments.size(); ++i) {
        const auto& frag = shape_result.fFragments[i];

        if (frag.fIsWhitespace) {
            if (in_word) {
                in_word = false;
                fMaps.fWordsMap.push_back({word_start, i - word_start, word_advance, word_ascent});
            }
        } else {
            fMaps.fNonWhitespaceMap.push_back({i, 1, 0, 0});

            if (!in_word) {
                in_word = true;
                word_start = i;
                word_advance = word_ascent = 0;
            }

            word_advance += frag.fAdvance;
            word_ascent   = std::min(word_ascent, frag.fAscent); // negative ascent
        }

        if (frag.fLineIndex != line) {
            SkASSERT(frag.fLineIndex == line + 1);
            fMaps.fLinesMap.push_back({line_start, i - line_start, line_advance, line_ascent});
            line = frag.fLineIndex;
            line_start = i;
            line_advance = line_ascent = 0;
        }

        line_advance += frag.fAdvance;
        line_ascent   = std::min(line_ascent, frag.fAscent); // negative ascent
    }

    if (i > word_start) {
        fMaps.fWordsMap.push_back({word_start, i - word_start, word_advance, word_ascent});
    }

    if (i > line_start) {
        fMaps.fLinesMap.push_back({line_start, i - line_start, line_advance, line_ascent});
    }
}

void TextAdapter::setText(const TextValue& txt) {
    fText.fCurrentValue = txt;
    this->onSync();
}

uint32_t TextAdapter::shaperFlags() const {
    uint32_t flags = Shaper::Flags::kNone;

    SkASSERT(!(fRequiresAnchorPoint && fAnimators.empty()));
    if (!fAnimators.empty() ) flags |= Shaper::Flags::kFragmentGlyphs;
    if (fRequiresAnchorPoint) flags |= Shaper::Flags::kTrackFragmentAdvanceAscent;

    return flags;
}

void TextAdapter::reshape() {
    const Shaper::TextDesc text_desc = {
        fText->fTypeface,
        fText->fTextSize,
        fText->fLineHeight,
        fText->fLineShift,
        fText->fAscent,
        fText->fHAlign,
        fText->fVAlign,
        fText->fResize,
        fText->fLineBreak,
        this->shaperFlags(),
    };
    const auto shape_result = Shaper::Shape(fText->fText, text_desc, fText->fBox, fFontMgr);

    if (fLogger && shape_result.fMissingGlyphCount > 0) {
        const auto msg = SkStringPrintf("Missing %zu glyphs for '%s'.",
                                        shape_result.fMissingGlyphCount,
                                        fText->fText.c_str());
        fLogger->log(Logger::Level::kWarning, msg.c_str());

        // This may trigger repeatedly when the text is animating.
        // To avoid spamming, only log once.
        fLogger = nullptr;
    }

    // Rebuild all fragments.
    // TODO: we can be smarter here and try to reuse the existing SG structure if needed.

    fRoot->clear();
    fFragments.clear();

    for (const auto& frag : shape_result.fFragments) {
        this->addFragment(frag);
    }

    if (!fAnimators.empty()) {
        // Range selectors require fragment domain maps.
        this->buildDomainMaps(shape_result);
    }

#if (0)
    // Enable for text box debugging/visualization.
    auto box_color = sksg::Color::Make(0xffff0000);
    box_color->setStyle(SkPaint::kStroke_Style);
    box_color->setStrokeWidth(1);
    box_color->setAntiAlias(true);

    auto bounds_color = sksg::Color::Make(0xff00ff00);
    bounds_color->setStyle(SkPaint::kStroke_Style);
    bounds_color->setStrokeWidth(1);
    bounds_color->setAntiAlias(true);

    fRoot->addChild(sksg::Draw::Make(sksg::Rect::Make(fText->fBox),
                                     std::move(box_color)));
    fRoot->addChild(sksg::Draw::Make(sksg::Rect::Make(shape_result.computeVisualBounds()),
                                     std::move(bounds_color)));
#endif
}

void TextAdapter::onSync() {
    if (!fText->fHasFill && !fText->fHasStroke) {
        return;
    }

    if (fText.hasChanged()) {
        this->reshape();
    }

    if (fFragments.empty()) {
        return;
    }

    // Seed props from the current text value.
    TextAnimator::ResolvedProps seed_props;
    seed_props.fill_color   = fText->fFillColor;
    seed_props.stroke_color = fText->fStrokeColor;

    TextAnimator::ModulatorBuffer buf;
    buf.resize(fFragments.size(), { seed_props, 0 });

    // Apply all animators to the modulator buffer.
    for (const auto& animator : fAnimators) {
        animator->modulateProps(fMaps, buf);
    }

    const TextAnimator::DomainMap* grouping_domain = nullptr;
    switch (fAnchorPointGrouping) {
        // for word/line grouping, we rely on domain map info
        case AnchorPointGrouping::kWord: grouping_domain = &fMaps.fWordsMap; break;
        case AnchorPointGrouping::kLine: grouping_domain = &fMaps.fLinesMap; break;
        // remaining grouping modes (character/all) do not need (or have) domain map data
        default: break;
    }

    size_t grouping_span_index = 0;
    SkV2           line_offset = { 0, 0 }; // cumulative line spacing

    // Finally, push all props to their corresponding fragment.
    for (const auto& line_span : fMaps.fLinesMap) {
        SkV2 line_spacing = { 0, 0 };
        float line_tracking = 0;
        bool line_has_tracking = false;

        // Tracking requires special treatment: unlike other props, its effect is not localized
        // to a single fragment, but requires re-alignment of the whole line.
        for (size_t i = line_span.fOffset; i < line_span.fOffset + line_span.fCount; ++i) {
            // Track the grouping domain span in parallel.
            if (grouping_domain && i >= (*grouping_domain)[grouping_span_index].fOffset +
                                        (*grouping_domain)[grouping_span_index].fCount) {
                grouping_span_index += 1;
                SkASSERT(i < (*grouping_domain)[grouping_span_index].fOffset +
                             (*grouping_domain)[grouping_span_index].fCount);
            }

            const auto& props = buf[i].props;
            const auto& frag  = fFragments[i];
            this->pushPropsToFragment(props, frag, fGroupingAlignment * .01f, // percentage
                                      grouping_domain ? &(*grouping_domain)[grouping_span_index]
                                                        : nullptr);

            line_tracking += props.tracking;
            line_has_tracking |= !SkScalarNearlyZero(props.tracking);

            line_spacing += props.line_spacing;
        }

        // line spacing of the first line is ignored (nothing to "space" against)
        if (&line_span != &fMaps.fLinesMap.front()) {
            // For each line, the actual spacing is an average of individual fragment spacing
            // (to preserve the "line").
            line_offset += line_spacing / line_span.fCount;
        }

        if (line_offset != SkV2{0, 0} || line_has_tracking) {
            this->adjustLineProps(buf, line_span, line_offset, line_tracking);
        }

    }
}

SkV2 TextAdapter::fragmentAnchorPoint(const FragmentRec& rec,
                                      const SkV2& grouping_alignment,
                                      const TextAnimator::DomainSpan* grouping_span) const {
    // Construct the following 2x ascent box:
    //
    //      -------------
    //     |             |
    //     |             | ascent
    //     |             |
    // ----+-------------+---------- baseline
    //   (pos)           |
    //     |             | ascent
    //     |             |
    //      -------------
    //         advance

    auto make_box = [](const SkPoint& pos, float advance, float ascent) {
        // note: negative ascent
        return SkRect::MakeXYWH(pos.fX, pos.fY + ascent, advance, -2 * ascent);
    };

    // Compute a grouping-dependent anchor point box.
    // The default anchor point is at the center, and gets adjusted relative to the bounds
    // based on |grouping_alignment|.
    auto anchor_box = [&]() -> SkRect {
        switch (fAnchorPointGrouping) {
        case AnchorPointGrouping::kCharacter:
            // Anchor box relative to each individual fragment.
            return make_box(rec.fOrigin, rec.fAdvance, rec.fAscent);
        case AnchorPointGrouping::kWord:
            // Fall through
        case AnchorPointGrouping::kLine: {
            SkASSERT(grouping_span);
            // Anchor box relative to the first fragment in the word/line.
            const auto& first_span_fragment = fFragments[grouping_span->fOffset];
            return make_box(first_span_fragment.fOrigin,
                            grouping_span->fAdvance,
                            grouping_span->fAscent);
        }
        case AnchorPointGrouping::kAll:
            // Anchor box is the same as the text box.
            return fText->fBox;
        }
        SkUNREACHABLE;
    };

    const auto ab = anchor_box();

    // Apply grouping alignment.
    const auto ap = SkV2 { ab.centerX() + ab.width()  * 0.5f * grouping_alignment.x,
                           ab.centerY() + ab.height() * 0.5f * grouping_alignment.y };

    // The anchor point is relative to the fragment position.
    return ap - SkV2 { rec.fOrigin.fX, rec.fOrigin.fY };
}

void TextAdapter::pushPropsToFragment(const TextAnimator::ResolvedProps& props,
                                      const FragmentRec& rec,
                                      const SkV2& grouping_alignment,
                                      const TextAnimator::DomainSpan* grouping_span) const {
    const auto anchor_point = this->fragmentAnchorPoint(rec, grouping_alignment, grouping_span);

    rec.fMatrixNode->setMatrix(
                SkM44::Translate(props.position.x + rec.fOrigin.x() + anchor_point.x,
                                 props.position.y + rec.fOrigin.y() + anchor_point.y,
                                 props.position.z)
              * SkM44::Rotate({ 1, 0, 0 }, SkDegreesToRadians(props.rotation.x))
              * SkM44::Rotate({ 0, 1, 0 }, SkDegreesToRadians(props.rotation.y))
              * SkM44::Rotate({ 0, 0, 1 }, SkDegreesToRadians(props.rotation.z))
              * SkM44::Scale(props.scale.x, props.scale.y, props.scale.z)
              * SkM44::Translate(-anchor_point.x, -anchor_point.y, 0));

    const auto scale_alpha = [](SkColor c, float o) {
        return SkColorSetA(c, SkScalarRoundToInt(o * SkColorGetA(c)));
    };

    if (rec.fFillColorNode) {
        rec.fFillColorNode->setColor(scale_alpha(props.fill_color, props.opacity));
    }
    if (rec.fStrokeColorNode) {
        rec.fStrokeColorNode->setColor(scale_alpha(props.stroke_color, props.opacity));
    }
    if (rec.fBlur) {
        rec.fBlur->setSigma({ props.blur.x * kBlurSizeToSigma,
                              props.blur.y * kBlurSizeToSigma });
    }
}

void TextAdapter::adjustLineProps(const TextAnimator::ModulatorBuffer& buf,
                                  const TextAnimator::DomainSpan& line_span,
                                  const SkV2& line_offset,
                                  float total_tracking) const {
    SkASSERT(line_span.fCount > 0);

    // AE tracking is defined per glyph, based on two components: |before| and |after|.
    // BodyMovin only exports "balanced" tracking values, where before == after == tracking / 2.
    //
    // Tracking is applied as a local glyph offset, and contributes to the line width for alignment
    // purposes.

    // The first glyph does not contribute |before| tracking, and the last one does not contribute
    // |after| tracking.  Rather than spill this logic into applyAnimators, post-adjust here.
    total_tracking -= 0.5f * (buf[line_span.fOffset].props.tracking +
                              buf[line_span.fOffset + line_span.fCount - 1].props.tracking);

    static const auto align_factor = [](SkTextUtils::Align a) {
        switch (a) {
        case SkTextUtils::kLeft_Align  : return  0.0f;
        case SkTextUtils::kCenter_Align: return -0.5f;
        case SkTextUtils::kRight_Align : return -1.0f;
        }

        SkASSERT(false);
        return 0.0f;
    };

    const auto align_offset = total_tracking * align_factor(fText->fHAlign);

    float tracking_acc = 0;
    for (size_t i = line_span.fOffset; i < line_span.fOffset + line_span.fCount; ++i) {
        const auto& props = buf[i].props;

        // No |before| tracking for the first glyph, nor |after| tracking for the last one.
        const auto track_before = i > line_span.fOffset
                                    ? props.tracking * 0.5f : 0.0f,
                   track_after  = i < line_span.fOffset + line_span.fCount - 1
                                    ? props.tracking * 0.5f : 0.0f,
                fragment_offset = align_offset + tracking_acc + track_before;

        const auto& frag = fFragments[i];
        const auto m = SkM44::Translate(line_offset.x + fragment_offset,
                                        line_offset.y) *
                       frag.fMatrixNode->getMatrix();
        frag.fMatrixNode->setMatrix(m);

        tracking_acc += track_before + track_after;
    }
}

} // namespace internal
} // namespace skottie
