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

#include "SkFontDescriptor.h"
#include "SkTestFontMgr.h"
#include "SkTestTypeface.h"
#include "sk_tool_utils.h"

#ifdef SK_XML
#include "SkTestSVGTypeface.h"
#endif

#include <vector>

namespace {

#include "test_font_monospace.inc"
#include "test_font_sans_serif.inc"
#include "test_font_serif.inc"
#include "test_font_index.inc"

class FontStyleSet final : public SkFontStyleSet {
public:
    FontStyleSet(const char* familyName) : fFamilyName(familyName) { }
    struct TypefaceEntry {
        TypefaceEntry(sk_sp<SkTypeface> typeface, SkFontStyle style, const char* styleName)
            : fTypeface(std::move(typeface))
            , fStyle(style)
            , fStyleName(styleName)
        {}
        sk_sp<SkTypeface> fTypeface;
        SkFontStyle fStyle;
        const char* fStyleName;
    };

    int count() override { return fTypefaces.size(); }

    void getStyle(int index, SkFontStyle* style, SkString* name) override {
        if (style) { *style = fTypefaces[index].fStyle; }
        if (name) { *name = fTypefaces[index].fStyleName; }
    }

    SkTypeface* createTypeface(int index) override {
        return SkRef(fTypefaces[index].fTypeface.get());
    }

    SkTypeface* matchStyle(const SkFontStyle& pattern) override {
        return this->matchStyleCSS3(pattern);
    }

    SkString getFamilyName() { return fFamilyName; }

    std::vector<TypefaceEntry> fTypefaces;
    SkString fFamilyName;
};

// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ //

class FontMgr final : public SkFontMgr {
public:
    FontMgr() {
        for (const auto& sub : gSubFonts) {
            sk_sp<SkTestTypeface> typeface =
                    sk_make_sp<SkTestTypeface>(sk_make_sp<SkTestFont>(sub.fFont), sub.fStyle);
            bool defaultFamily = false;
            if (&sub - gSubFonts == gDefaultFontIndex) {
                defaultFamily = true;
                fDefaultTypeface = typeface;
            }
            bool found = false;
            for (const auto& family : fFamilies) {
                if (family->getFamilyName().equals(sub.fFamilyName)) {
                    family->fTypefaces.emplace_back(std::move(typeface), sub.fStyle, sub.fStyleName);
                    found = true;
                    if (defaultFamily) {
                        fDefaultFamily = family;
                    }
                }
            }
            if (!found) {
                fFamilies.emplace_back(sk_make_sp<FontStyleSet>(sub.fFamilyName));
                fFamilies.back()->fTypefaces.emplace_back(std::move(typeface), sub.fStyle, sub.fStyleName);
                if (defaultFamily) {
                    fDefaultFamily = fFamilies.back();
                }
            }
        }
        #ifdef SK_XML
        fFamilies.emplace_back(sk_make_sp<FontStyleSet>("Emoji"));
        fFamilies.back()->fTypefaces.emplace_back(SkTestSVGTypeface::Default(), SkFontStyle::Normal(), "Normal");
        #endif
    }

    int onCountFamilies() const override { return fFamilies.size(); }

    void onGetFamilyName(int index, SkString* familyName) const override {
        *familyName = fFamilies[index]->getFamilyName();
    }

    SkFontStyleSet* onCreateStyleSet(int index) const override {
        sk_sp<SkFontStyleSet> ref = fFamilies[index];
        return ref.release();
    }

    SkFontStyleSet* onMatchFamily(const char familyName[]) const override {
        if (familyName) {
            if (strstr(familyName,  "ono")) { return this->createStyleSet(0); }
            if (strstr(familyName,  "ans")) { return this->createStyleSet(1); }
            if (strstr(familyName, "erif")) { return this->createStyleSet(2); }
            #ifdef SK_XML
            if (strstr(familyName,  "oji")) { return this->createStyleSet(6); }
            #endif
        }
        return nullptr;
    }


    SkTypeface* onMatchFamilyStyle(const char familyName[],
                                   const SkFontStyle& style) const override {
        sk_sp<SkFontStyleSet> styleSet(this->matchFamily(familyName));
        return styleSet->matchStyle(style);
    }

    SkTypeface* onMatchFamilyStyleCharacter(const char familyName[],
                                            const SkFontStyle& style,
                                            const char* bcp47[], int bcp47Count,
                                            SkUnichar character) const override {
        (void)bcp47;
        (void)bcp47Count;
        (void)character;
        return this->matchFamilyStyle(familyName, style);
    }

    SkTypeface* onMatchFaceStyle(const SkTypeface* tf,
                                 const SkFontStyle& style) const override {
        SkString familyName;
        tf->getFamilyName(&familyName);
        return this->matchFamilyStyle(familyName.c_str(), style);
    }

    sk_sp<SkTypeface> onMakeFromData(sk_sp<SkData>, int ttcIndex) const override {
        return nullptr;
    }
    sk_sp<SkTypeface> onMakeFromStreamIndex(std::unique_ptr<SkStreamAsset>,
                                            int ttcIndex) const override {
        return nullptr;
    }
    sk_sp<SkTypeface> onMakeFromStreamArgs(std::unique_ptr<SkStreamAsset>,
                                           const SkFontArguments&) const override {
        return nullptr;
    }
    sk_sp<SkTypeface> onMakeFromFontData(std::unique_ptr<SkFontData>) const override {
        return nullptr;
    }
    sk_sp<SkTypeface> onMakeFromFile(const char path[], int ttcIndex) const override {
        return nullptr;
    }

    sk_sp<SkTypeface> onLegacyMakeTypeface(const char familyName[],
                                           SkFontStyle style) const override {
        if (familyName == nullptr) {
            return sk_sp<SkTypeface>(fDefaultFamily->matchStyle(style));
        }
        sk_sp<SkTypeface> typeface = sk_sp<SkTypeface>(this->matchFamilyStyle(familyName, style));
        if (!typeface) {
            typeface = fDefaultTypeface;
        }
        return typeface;
    }

private:
    std::vector<sk_sp<FontStyleSet>> fFamilies;
    sk_sp<FontStyleSet> fDefaultFamily;
    sk_sp<SkTypeface> fDefaultTypeface;
};
}

namespace sk_tool_utils {
sk_sp<SkFontMgr> MakePortableFontMgr() { return sk_make_sp<FontMgr>(); }
} // namespace sk_tool_utils
