/*
 * 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/effects/Effects.h"

#include "modules/skottie/src/SkottieJson.h"
#include "modules/sksg/include/SkSGRenderEffect.h"
#include "src/utils/SkJSON.h"

namespace skottie {
namespace internal {

EffectBuilder::EffectBuilder(const AnimationBuilder* abuilder, const SkSize& layer_size)
    : fBuilder(abuilder)
    , fLayerSize(layer_size) {}

EffectBuilder::EffectBuilderT EffectBuilder::findBuilder(const skjson::ObjectValue& jeffect) const {
    // First, try assigned types.
    enum : int32_t {
        kTint_Effect         = 20,
        kFill_Effect         = 21,
        kTritone_Effect      = 23,
        kDropShadow_Effect   = 25,
        kRadialWipe_Effect   = 26,
        kGaussianBlur_Effect = 29,
    };

    const auto ty = ParseDefault<int>(jeffect["ty"], -1);

    switch (ty) {
    case kTint_Effect:
        return &EffectBuilder::attachTintEffect;
    case kFill_Effect:
        return &EffectBuilder::attachFillEffect;
    case kTritone_Effect:
        return &EffectBuilder::attachTritoneEffect;
    case kDropShadow_Effect:
        return &EffectBuilder::attachDropShadowEffect;
    case kRadialWipe_Effect:
        return &EffectBuilder::attachRadialWipeEffect;
    case kGaussianBlur_Effect:
        return &EffectBuilder::attachGaussianBlurEffect;
    default:
        break;
    }

    // Some effects don't have an assigned type, but the data is still present.
    // Try a name-based lookup.

    static constexpr char kGradientEffectMN[] = "ADBE Ramp",
                           kHueSaturationMN[] = "ADBE HUE SATURATION",
                            kLevelsEffectMN[] = "ADBE Easy Levels2",
                        kLinearWipeEffectMN[] = "ADBE Linear Wipe",
                        kMotionTileEffectMN[] = "ADBE Tile",
                         kTransformEffectMN[] = "ADBE Geometry2",
                    kVenetianBlindsEffectMN[] = "ADBE Venetian Blinds";

    if (const skjson::StringValue* mn = jeffect["mn"]) {
        if (!strcmp(mn->begin(), kGradientEffectMN)) {
            return &EffectBuilder::attachGradientEffect;
        }
        if (!strcmp(mn->begin(), kHueSaturationMN)) {
            return &EffectBuilder::attachHueSaturationEffect;
        }
        if (!strcmp(mn->begin(), kLevelsEffectMN)) {
            return &EffectBuilder::attachLevelsEffect;
        }
        if (!strcmp(mn->begin(), kLinearWipeEffectMN)) {
            return &EffectBuilder::attachLinearWipeEffect;
        }
        if (!strcmp(mn->begin(), kMotionTileEffectMN)) {
            return &EffectBuilder::attachMotionTileEffect;
        }
        if (!strcmp(mn->begin(), kTransformEffectMN)) {
            return &EffectBuilder::attachTransformEffect;
        }
        if (!strcmp(mn->begin(), kVenetianBlindsEffectMN)) {
            return &EffectBuilder::attachVenetianBlindsEffect;
        }
    }

    fBuilder->log(Logger::Level::kWarning, nullptr, "Unsupported layer effect type: %d.", ty);

    return nullptr;
}

sk_sp<sksg::RenderNode> EffectBuilder::attachEffects(const skjson::ArrayValue& jeffects,
                                                     sk_sp<sksg::RenderNode> layer) const {
    if (!layer) {
        return nullptr;
    }

    for (const skjson::ObjectValue* jeffect : jeffects) {
        if (!jeffect) {
            continue;
        }

        const auto builder = this->findBuilder(*jeffect);
        const skjson::ArrayValue* jprops = (*jeffect)["ef"];
        if (!builder || !jprops) {
            continue;
        }

        const AnimationBuilder::AutoPropertyTracker apt(fBuilder, *jeffect);
        layer = (this->*builder)(*jprops, std::move(layer));

        if (!layer) {
            fBuilder->log(Logger::Level::kError, jeffect, "Invalid layer effect.");
            return nullptr;
        }
    }

    return layer;
}

const skjson::Value& EffectBuilder::GetPropValue(const skjson::ArrayValue& jprops,
                                                 size_t prop_index) {
    static skjson::NullValue kNull;

    if (prop_index >= jprops.size()) {
        return kNull;
    }

    const skjson::ObjectValue* jprop = jprops[prop_index];

    return jprop ? (*jprop)["v"] : kNull;
}

MaskFilterEffectBase::MaskFilterEffectBase(sk_sp<sksg::RenderNode> child, const SkSize& ls)
    : fMaskNode(sksg::MaskFilter::Make(nullptr))
    , fMaskEffectNode(sksg::MaskFilterEffect::Make(std::move(child), fMaskNode))
    , fLayerSize(ls) {}

MaskFilterEffectBase::~MaskFilterEffectBase() = default;

void MaskFilterEffectBase::apply() const {
    const auto minfo = this->onMakeMask();

    fMaskEffectNode->setVisible(minfo.fVisible);
    fMaskNode->setMaskFilter(std::move(minfo.fMask));
}

} // namespace internal
} // namespace skottie
