/*
 * Copyright 2018 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/SkottiePriv.h"

#include "include/core/SkData.h"
#include "include/core/SkFontMgr.h"
#include "include/core/SkTypes.h"
#include "modules/skottie/src/SkottieJson.h"
#include "modules/skottie/src/text/TextAdapter.h"
#include "modules/skottie/src/text/TextAnimator.h"
#include "modules/skottie/src/text/TextValue.h"
#include "modules/sksg/include/SkSGDraw.h"
#include "modules/sksg/include/SkSGGroup.h"
#include "modules/sksg/include/SkSGPaint.h"
#include "modules/sksg/include/SkSGPath.h"
#include "modules/sksg/include/SkSGText.h"
#include "src/base/SkTSearch.h"

#include <string.h>

namespace skottie {
namespace internal {

namespace {

template <typename T, typename TMap>
const char* parse_map(const TMap& map, const char* str, T* result) {
    // ignore leading whitespace
    while (*str == ' ') ++str;

    const char* next_tok = strchr(str, ' ');

    if (const auto len = next_tok ? (next_tok - str) : strlen(str)) {
        for (const auto& e : map) {
            const char* key = std::get<0>(e);
            if (!strncmp(str, key, len) && key[len] == '\0') {
                *result = std::get<1>(e);
                return str + len;
            }
        }
    }

    return str;
}

SkFontStyle FontStyle(const AnimationBuilder* abuilder, const char* style) {
    static constexpr std::tuple<const char*, SkFontStyle::Weight> gWeightMap[] = {
        { "regular"   , SkFontStyle::kNormal_Weight     },
        { "medium"    , SkFontStyle::kMedium_Weight     },
        { "bold"      , SkFontStyle::kBold_Weight       },
        { "light"     , SkFontStyle::kLight_Weight      },
        { "black"     , SkFontStyle::kBlack_Weight      },
        { "thin"      , SkFontStyle::kThin_Weight       },
        { "extra"     , SkFontStyle::kExtraBold_Weight  },
        { "extrabold" , SkFontStyle::kExtraBold_Weight  },
        { "extralight", SkFontStyle::kExtraLight_Weight },
        { "extrablack", SkFontStyle::kExtraBlack_Weight },
        { "semibold"  , SkFontStyle::kSemiBold_Weight   },
        { "hairline"  , SkFontStyle::kThin_Weight       },
        { "normal"    , SkFontStyle::kNormal_Weight     },
        { "plain"     , SkFontStyle::kNormal_Weight     },
        { "standard"  , SkFontStyle::kNormal_Weight     },
        { "roman"     , SkFontStyle::kNormal_Weight     },
        { "heavy"     , SkFontStyle::kBlack_Weight      },
        { "demi"      , SkFontStyle::kSemiBold_Weight   },
        { "demibold"  , SkFontStyle::kSemiBold_Weight   },
        { "ultra"     , SkFontStyle::kExtraBold_Weight  },
        { "ultrabold" , SkFontStyle::kExtraBold_Weight  },
        { "ultrablack", SkFontStyle::kExtraBlack_Weight },
        { "ultraheavy", SkFontStyle::kExtraBlack_Weight },
        { "ultralight", SkFontStyle::kExtraLight_Weight },
    };
    static constexpr std::tuple<const char*, SkFontStyle::Slant> gSlantMap[] = {
        { "italic" , SkFontStyle::kItalic_Slant  },
        { "oblique", SkFontStyle::kOblique_Slant },
    };

    auto weight = SkFontStyle::kNormal_Weight;
    auto slant  = SkFontStyle::kUpright_Slant;

    // style is case insensitive.
    SkAutoAsciiToLC lc_style(style);
    style = lc_style.lc();
    style = parse_map(gWeightMap, style, &weight);
    style = parse_map(gSlantMap , style, &slant );

    // ignore trailing whitespace
    while (*style == ' ') ++style;

    if (*style) {
        abuilder->log(Logger::Level::kWarning, nullptr, "Unknown font style: %s.", style);
    }

    return SkFontStyle(weight, SkFontStyle::kNormal_Width, slant);
}

} // namespace

bool AnimationBuilder::FontInfo::matches(const char family[], const char style[]) const {
    return 0 == strcmp(fFamily.c_str(), family)
        && 0 == strcmp(fStyle.c_str(), style);
}

void AnimationBuilder::parseFonts(const skjson::ObjectValue* jfonts,
                                  const skjson::ArrayValue* jchars) {
    // Optional array of font entries, referenced (by name) from text layer document nodes. E.g.
    // "fonts": {
    //        "list": [
    //            {
    //                "ascent": 75,
    //                "fClass": "",
    //                "fFamily": "Roboto",
    //                "fName": "Roboto-Regular",
    //                "fPath": "https://fonts.googleapis.com/css?family=Roboto",
    //                "fPath": "",
    //                "fStyle": "Regular",
    //                "fWeight": "",
    //                "origin": 1
    //            }
    //        ]
    //    },
    const skjson::ArrayValue* jlist = jfonts
            ? static_cast<const skjson::ArrayValue*>((*jfonts)["list"])
            : nullptr;
    if (!jlist) {
        return;
    }

    // First pass: collect font info.
    for (const skjson::ObjectValue* jfont : *jlist) {
        if (!jfont) {
            continue;
        }

        const skjson::StringValue* jname   = (*jfont)["fName"];
        const skjson::StringValue* jfamily = (*jfont)["fFamily"];
        const skjson::StringValue* jstyle  = (*jfont)["fStyle"];
        const skjson::StringValue* jpath   = (*jfont)["fPath"];

        if (!jname   || !jname->size() ||
            !jfamily || !jfamily->size() ||
            !jstyle) {
            this->log(Logger::Level::kError, jfont, "Invalid font.");
            continue;
        }

        fFonts.set(SkString(jname->begin(), jname->size()),
                  {
                      SkString(jfamily->begin(), jfamily->size()),
                      SkString( jstyle->begin(),  jstyle->size()),
                      jpath ? SkString(  jpath->begin(),   jpath->size()) : SkString(),
                      ParseDefault((*jfont)["ascent"] , 0.0f),
                      nullptr, // placeholder
                      CustomFont::Builder()
                  });
    }

    const auto has_comp_glyphs = [](const skjson::ArrayValue* jchars) {
        if (!jchars) {
            return false;
        }

        for (const skjson::ObjectValue* jchar : *jchars) {
            if (!jchar) {
                continue;
            }
            if (ParseDefault<int>((*jchar)["t"], 0) == 1) {
                return true;
            }
        }

        return false;
    };

    // Historically, Skottie has been loading native fonts before embedded glyphs, unless
    // the opposite is explicitly requested via kPreferEmbeddedFonts.  That's mostly because
    // embedded glyphs used to be just a path representation of system fonts at export time,
    // (and thus lower quality).
    //
    // OTOH embedded glyph *compositions* must be prioritized, as they are presumably more
    // expressive than the system font equivalent.
    const auto prioritize_embedded_fonts =
            (fFlags & Animation::Builder::kPreferEmbeddedFonts) || has_comp_glyphs(jchars);

    // Optional pass.
    if (jchars && prioritize_embedded_fonts && this->resolveEmbeddedTypefaces(*jchars)) {
        return;
    }

    // Native typeface resolution.
    if (this->resolveNativeTypefaces()) {
        return;
    }

    // Embedded typeface fallback.
    if (jchars && !prioritize_embedded_fonts) {
        this->resolveEmbeddedTypefaces(*jchars);
    }
}

bool AnimationBuilder::resolveNativeTypefaces() {
    bool has_unresolved = false;

    fFonts.foreach([&](const SkString& name, FontInfo* finfo) {
        SkASSERT(finfo);

        if (finfo->fTypeface) {
            // Already resolved from glyph paths.
            return;
        }

        const auto& fmgr = fLazyFontMgr.get();

        // Typeface fallback order:
        //   1) externally-loaded font (provided by the embedder)
        //   2) system font (family/style)
        //   3) system default

        finfo->fTypeface = fResourceProvider->loadTypeface(name.c_str(), finfo->fPath.c_str());

        // legacy API fallback
        // TODO: remove after client migration
        if (!finfo->fTypeface) {
            finfo->fTypeface = fmgr->makeFromData(
                    fResourceProvider->loadFont(name.c_str(), finfo->fPath.c_str()));
        }

        if (!finfo->fTypeface) {
            finfo->fTypeface = fmgr->matchFamilyStyle(finfo->fFamily.c_str(),
                                                      FontStyle(this, finfo->fStyle.c_str()));

            if (!finfo->fTypeface) {
                this->log(Logger::Level::kError, nullptr, "Could not create typeface for %s|%s.",
                          finfo->fFamily.c_str(), finfo->fStyle.c_str());
                // Last resort.
                finfo->fTypeface = fmgr->legacyMakeTypeface(nullptr,
                                                            FontStyle(this, finfo->fStyle.c_str()));

                has_unresolved |= !finfo->fTypeface;
            }
        }
    });

    return !has_unresolved;
}

bool AnimationBuilder::resolveEmbeddedTypefaces(const skjson::ArrayValue& jchars) {
    // Optional array of glyphs, to be associated with one of the declared fonts. E.g.
    // "chars": [
    //     {
    //         "fFamily": "Roboto",       // part of the font key
    //         "style": "Regular",        // part of the font key
    //         ...                        // glyph data
    //    }
    // ]
    FontInfo* current_font = nullptr;

    for (const skjson::ObjectValue* jchar : jchars) {
        if (!jchar) {
            continue;
        }

        const skjson::StringValue* jfamily = (*jchar)["fFamily"];
        const skjson::StringValue* jstyle  = (*jchar)["style"]; // "style", not "fStyle"...

        if (!jfamily || !jstyle) {
            this->log(Logger::Level::kError, jchar, "Invalid glyph.");
            continue;
        }
        const auto* family = jfamily->begin();
        const auto* style  = jstyle->begin();

        // Locate (and cache) the font info. Unlike text nodes, glyphs reference the font by
        // (family, style) -- not by name :(  For now this performs a linear search over *all*
        // fonts: generally there are few of them, and glyph definitions are font-clustered.
        // If problematic, we can refactor as a two-level hashmap.
        if (!current_font || !current_font->matches(family, style)) {
            current_font = nullptr;
            fFonts.foreach([&](const SkString& name, FontInfo* finfo) {
                if (finfo->matches(family, style)) {
                    current_font = finfo;
                    // TODO: would be nice to break early here...
                }
            });
            if (!current_font) {
                this->log(Logger::Level::kError, nullptr,
                          "Font not found (%s, %s).", family, style);
                continue;
            }
        }

        if (!current_font->fCustomFontBuilder.parseGlyph(this, *jchar)) {
            this->log(Logger::Level::kError, jchar, "Invalid glyph.");
        }
    }

    // Final pass to commit custom typefaces.
    auto has_unresolved = false;
    std::vector<std::unique_ptr<CustomFont>> custom_fonts;
    fFonts.foreach([&has_unresolved, &custom_fonts](const SkString&, FontInfo* finfo) {
        if (finfo->fTypeface) {
            return; // already resolved
        }

        auto font = finfo->fCustomFontBuilder.detach();

        finfo->fTypeface = font->typeface();

        if (font->glyphCompCount() > 0) {
            custom_fonts.push_back(std::move(font));
        }

        has_unresolved |= !finfo->fTypeface;
    });

    // Stash custom font data for later use.
    if (!custom_fonts.empty()) {
        custom_fonts.shrink_to_fit();
        fCustomGlyphMapper = sk_make_sp<CustomFont::GlyphCompMapper>(std::move(custom_fonts));
    }

    return !has_unresolved;
}

sk_sp<sksg::RenderNode> AnimationBuilder::attachTextLayer(const skjson::ObjectValue& jlayer,
                                                          LayerInfo*) const {
    return this->attachDiscardableAdapter<TextAdapter>(jlayer,
                                                       this,
                                                       fLazyFontMgr.getMaybeNull(),
                                                       fCustomGlyphMapper,
                                                       fLogger);
}

const AnimationBuilder::FontInfo* AnimationBuilder::findFont(const SkString& font_name) const {
    return fFonts.find(font_name);
}

} // namespace internal
} // namespace skottie
