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

#include "include/core/SkCanvas.h"
#include "include/core/SkImage.h"
#include "include/core/SkString.h"
#include "include/core/SkTypes.h"
#include "modules/skottie/include/Skottie.h"
#include "modules/sksg/include/SkSGInvalidationController.h"

#include <string>
#include <vector>

#include <emscripten.h>
#include <emscripten/bind.h>
#include "modules/canvaskit/WasmCommon.h"

#if SK_INCLUDE_MANAGED_SKOTTIE
#include "modules/skottie/include/SkottieProperty.h"
#include "modules/skottie/utils/SkottieUtils.h"
#include "modules/skresources/include/SkResources.h"
#endif // SK_INCLUDE_MANAGED_SKOTTIE

using namespace emscripten;

#if SK_INCLUDE_MANAGED_SKOTTIE
namespace {

// WebTrack wraps a JS object that has a 'seek' method.
// Playback logic is kept there.
class WebTrack final : public skresources::ExternalTrackAsset {
public:
    explicit WebTrack(emscripten::val player) : fPlayer(std::move(player)) {}

private:
    void seek(float t) override {
        fPlayer.call<void>("seek", val(t));
    }

    const emscripten::val fPlayer;
};

class SkottieAssetProvider : public skottie::ResourceProvider {
public:
    ~SkottieAssetProvider() override = default;

    // Tried using a map, but that gave strange errors like
    // https://emscripten.org/docs/porting/guidelines/function_pointer_issues.html
    // Not entirely sure why, but perhaps the iterator in the map was
    // confusing enscripten.
    using AssetVec = std::vector<std::pair<SkString, sk_sp<SkData>>>;

    static sk_sp<SkottieAssetProvider> Make(AssetVec assets, emscripten::val soundMap) {
        return sk_sp<SkottieAssetProvider>(new SkottieAssetProvider(std::move(assets),
                                                                    std::move(soundMap)));
    }

    sk_sp<skottie::ImageAsset> loadImageAsset(const char[] /* path */,
                                              const char name[],
                                              const char[] /* id */) const override {
        // For CK/Skottie we ignore paths & IDs, and identify images based solely on name.
        if (auto data = this->findAsset(name)) {
            return skresources::MultiFrameImageAsset::Make(std::move(data));
        }

        return nullptr;
    }

    sk_sp<skresources::ExternalTrackAsset> loadAudioAsset(const char[] /* path */,
                                                          const char[] /* name */,
                                                          const char id[]) override {
        emscripten::val player = this->findSoundAsset(id);
        if (player.as<bool>()) {
            return sk_make_sp<WebTrack>(std::move(player));
        }

        return nullptr;
    }

    sk_sp<SkData> loadFont(const char name[], const char[] /* url */) const override {
        // Same as images paths, we ignore font URLs.
        return this->findAsset(name);
    }

    sk_sp<SkData> load(const char[]/*path*/, const char name[]) const override {
        // Ignore paths.
        return this->findAsset(name);
    }

private:
    explicit SkottieAssetProvider(AssetVec assets, emscripten::val soundMap)
    : fAssets(std::move(assets))
    , fSoundMap(std::move(soundMap)) {}

    sk_sp<SkData> findAsset(const char name[]) const {
        for (const auto& asset : fAssets) {
            if (asset.first.equals(name)) {
                return asset.second;
            }
        }

        SkDebugf("Could not find %s\n", name);
        return nullptr;
    }

    emscripten::val findSoundAsset(const char name[]) const {
        if (fSoundMap.as<bool>() && fSoundMap.hasOwnProperty("getPlayer")) {
            emscripten::val player = fSoundMap.call<emscripten::val>("getPlayer", val(name));
            if (player.as<bool>() && player.hasOwnProperty("seek")) {
                return player;
            }
        }
        return emscripten::val::null();
    }

    const AssetVec fAssets;
    const emscripten::val fSoundMap;
};

// Wraps a JS object with 'onError' and 'onWarning' methods.
class JSLogger final : public skottie::Logger {
public:
    static sk_sp<JSLogger> Make(emscripten::val logger) {
        return logger.as<bool>()
            && logger.hasOwnProperty(kWrnFunc)
            && logger.hasOwnProperty(kErrFunc)
                ? sk_sp<JSLogger>(new JSLogger(std::move(logger)))
                : nullptr;
    }

private:
    explicit JSLogger(emscripten::val logger) : fLogger(std::move(logger)) {}

    void log(Level lvl, const char msg[], const char* json) override {
        const auto* func = lvl == Level::kError ? kErrFunc : kWrnFunc;
        fLogger.call<void>(func, std::string(msg), std::string(json));
    }

    static constexpr char kWrnFunc[] = "onWarning",
                          kErrFunc[] = "onError";

    const emscripten::val fLogger;
};

class ManagedAnimation final : public SkRefCnt {
public:
    static sk_sp<ManagedAnimation> Make(const std::string& json,
                                        sk_sp<skottie::ResourceProvider> rp,
                                        std::string prop_prefix,
                                        emscripten::val logger) {
        auto mgr = std::make_unique<skottie_utils::CustomPropertyManager>(
                        skottie_utils::CustomPropertyManager::Mode::kCollapseProperties,
                        prop_prefix.empty() ? nullptr : prop_prefix.c_str());
        static constexpr char kInterceptPrefix[] = "__";
        auto pinterceptor =
            sk_make_sp<skottie_utils::ExternalAnimationPrecompInterceptor>(rp, kInterceptPrefix);
        auto animation = skottie::Animation::Builder()
                            .setMarkerObserver(mgr->getMarkerObserver())
                            .setPropertyObserver(mgr->getPropertyObserver())
                            .setResourceProvider(std::move(rp))
                            .setPrecompInterceptor(std::move(pinterceptor))
                            .setLogger(JSLogger::Make(std::move(logger)))
                            .make(json.c_str(), json.size());

        return animation
            ? sk_sp<ManagedAnimation>(new ManagedAnimation(std::move(animation), std::move(mgr)))
            : nullptr;
    }

    ~ManagedAnimation() override = default;

    // skottie::Animation API
    void render(SkCanvas* canvas, const SkRect* dst) const { fAnimation->render(canvas, dst); }
    // Returns a damage rect.
    SkRect seek(SkScalar t) {
        sksg::InvalidationController ic;
        fAnimation->seek(t, &ic);
        return ic.bounds();
    }
    // Returns a damage rect.
    SkRect seekFrame(double t) {
        sksg::InvalidationController ic;
        fAnimation->seekFrame(t, &ic);
        return ic.bounds();
    }
    double duration() const { return fAnimation->duration(); }
    double fps() const { return fAnimation->fps(); }
    const SkSize& size() const { return fAnimation->size(); }
    std::string version() const { return std::string(fAnimation->version().c_str()); }

    // CustomPropertyManager API
    JSArray getColorProps() const {
        JSArray props = emscripten::val::array();

        for (const auto& cp : fPropMgr->getColorProps()) {
            JSObject prop = emscripten::val::object();
            prop.set("key", cp);
            prop.set("value", fPropMgr->getColor(cp));
            props.call<void>("push", prop);
        }

        return props;
    }

    JSArray getOpacityProps() const {
        JSArray props = emscripten::val::array();

        for (const auto& op : fPropMgr->getOpacityProps()) {
            JSObject prop = emscripten::val::object();
            prop.set("key", op);
            prop.set("value", fPropMgr->getOpacity(op));
            props.call<void>("push", prop);
        }

        return props;
    }

    bool setColor(const std::string& key, SkColor c) {
        return fPropMgr->setColor(key, c);
    }

    bool setOpacity(const std::string& key, float o) {
        return fPropMgr->setOpacity(key, o);
    }

    JSArray getMarkers() const {
        JSArray markers = emscripten::val::array();
        for (const auto& m : fPropMgr->markers()) {
            JSObject marker = emscripten::val::object();
            marker.set("name", m.name);
            marker.set("t0"  , m.t0);
            marker.set("t1"  , m.t1);
            markers.call<void>("push", marker);
        }
        return markers;
    }

private:
    ManagedAnimation(sk_sp<skottie::Animation> animation,
                     std::unique_ptr<skottie_utils::CustomPropertyManager> propMgr)
        : fAnimation(std::move(animation))
        , fPropMgr(std::move(propMgr))
    {}

    const sk_sp<skottie::Animation>                             fAnimation;
    const std::unique_ptr<skottie_utils::CustomPropertyManager> fPropMgr;
};

} // anonymous ns
#endif // SK_INCLUDE_MANAGED_SKOTTIE

EMSCRIPTEN_BINDINGS(Skottie) {
    // Animation things (may eventually go in own library)
    class_<skottie::Animation>("Animation")
        .smart_ptr<sk_sp<skottie::Animation>>("sk_sp<Animation>")
        .function("version", optional_override([](skottie::Animation& self)->std::string {
            return std::string(self.version().c_str());
        }))
        .function("_size", optional_override([](skottie::Animation& self,
                                                uintptr_t /* float* */ oPtr)->void {
            SkSize* output = reinterpret_cast<SkSize*>(oPtr);
            *output = self.size();
        }))
        .function("duration", &skottie::Animation::duration)
        .function("fps"     , &skottie::Animation::fps)
        .function("seek", optional_override([](skottie::Animation& self, SkScalar t)->void {
            self.seek(t);
        }))
        .function("seekFrame", optional_override([](skottie::Animation& self, double t)->void {
            self.seekFrame(t);
        }))
        .function("_render", optional_override([](skottie::Animation& self, SkCanvas* canvas,
                                                  uintptr_t /* float* */ fPtr)->void {
            const SkRect* dst = reinterpret_cast<const SkRect*>(fPtr);
            self.render(canvas, dst);
        }), allow_raw_pointers());

    function("MakeAnimation", optional_override([](std::string json)->sk_sp<skottie::Animation> {
        return skottie::Animation::Make(json.c_str(), json.length());
    }));
    constant("skottie", true);

#if SK_INCLUDE_MANAGED_SKOTTIE
    class_<ManagedAnimation>("ManagedAnimation")
        .smart_ptr<sk_sp<ManagedAnimation>>("sk_sp<ManagedAnimation>")
        .function("version"   , &ManagedAnimation::version)
        .function("_size", optional_override([](ManagedAnimation& self,
                                                uintptr_t /* float* */ oPtr)->void {
            SkSize* output = reinterpret_cast<SkSize*>(oPtr);
            *output = self.size();
        }))
        .function("duration"  , &ManagedAnimation::duration)
        .function("fps"       , &ManagedAnimation::fps)
        .function("_render", optional_override([](ManagedAnimation& self, SkCanvas* canvas,
                                                  uintptr_t /* float* */ fPtr)->void {
            const SkRect* dst = reinterpret_cast<const SkRect*>(fPtr);
            self.render(canvas, dst);
        }), allow_raw_pointers())
        .function("_seek", optional_override([](ManagedAnimation& self, SkScalar t,
                                                uintptr_t /* float* */ fPtr) {
            SkRect* damageRect = reinterpret_cast<SkRect*>(fPtr);
            damageRect[0] = self.seek(t);
        }))
        .function("_seekFrame", optional_override([](ManagedAnimation& self, double frame,
                                                     uintptr_t /* float* */ fPtr) {
            SkRect* damageRect = reinterpret_cast<SkRect*>(fPtr);
            damageRect[0] = self.seekFrame(frame);
        }))
        .function("seekFrame" , &ManagedAnimation::seekFrame)
        .function("_setColor"  , optional_override([](ManagedAnimation& self, const std::string& key, uintptr_t /* float* */ cPtr) {
            float* fourFloats = reinterpret_cast<float*>(cPtr);
            SkColor4f color = { fourFloats[0], fourFloats[1], fourFloats[2], fourFloats[3] };
            self.setColor(key, color.toSkColor());
        }))
        .function("setOpacity", &ManagedAnimation::setOpacity)
        .function("getMarkers", &ManagedAnimation::getMarkers)
        .function("getColorProps"  , &ManagedAnimation::getColorProps)
        .function("getOpacityProps", &ManagedAnimation::getOpacityProps);

    function("_MakeManagedAnimation", optional_override([](std::string json,
                                                           size_t assetCount,
                                                           uintptr_t /* char**     */ nptr,
                                                           uintptr_t /* uint8_t**  */ dptr,
                                                           uintptr_t /* size_t*    */ sptr,
                                                           std::string prop_prefix,
                                                           emscripten::val soundMap,
                                                           emscripten::val logger)
                                                        ->sk_sp<ManagedAnimation> {
        // See the comment in canvaskit_bindings.cpp about the use of uintptr_t
        const auto assetNames = reinterpret_cast<char**   >(nptr);
        const auto assetDatas = reinterpret_cast<uint8_t**>(dptr);
        const auto assetSizes = reinterpret_cast<size_t*  >(sptr);

        SkottieAssetProvider::AssetVec assets;
        assets.reserve(assetCount);

        for (size_t i = 0; i < assetCount; i++) {
            auto name  = SkString(assetNames[i]);
            auto bytes = SkData::MakeFromMalloc(assetDatas[i], assetSizes[i]);
            assets.push_back(std::make_pair(std::move(name), std::move(bytes)));
        }

        return ManagedAnimation::Make(json,
                                      skresources::DataURIResourceProviderProxy::Make(
                                          SkottieAssetProvider::Make(std::move(assets),
                                                                     std::move(soundMap))),
                                      prop_prefix, std::move(logger));
    }));
    constant("managed_skottie", true);
#endif // SK_INCLUDE_MANAGED_SKOTTIE
}
