/*
 * Copyright 2020 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/Adapter.h"
#include "modules/skottie/src/SkottieJson.h"
#include "modules/skottie/src/SkottiePriv.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/skottie/src/layers/shapelayer/ShapeLayer.h"
#include "modules/sksg/include/SkSGGeometryEffect.h"
#include "modules/sksg/include/SkSGPaint.h"

namespace skottie {
namespace internal {

namespace  {

class FillStrokeAdapter final : public DiscardableAdapterBase<FillStrokeAdapter, sksg::PaintNode> {
public:
    enum class Type { kFill, kStroke };

    FillStrokeAdapter(const skjson::ObjectValue& jpaint,
                      const AnimationBuilder& abuilder,
                      sk_sp<sksg::PaintNode> paint_node,
                      sk_sp<AnimatablePropertyContainer> gradient_adapter,
                      Type type)
        : INHERITED(std::move(paint_node))
        , fShaderType(gradient_adapter ? ShaderType::kGradient : ShaderType::kColor) {

        this->attachDiscardableAdapter(std::move(gradient_adapter));

        this->bind(abuilder, jpaint["o"], fOpacity);

        this->node()->setAntiAlias(true);

        if (type == Type::kStroke) {
            this->bind(abuilder, jpaint["w"], fStrokeWidth);

            this->node()->setStyle(SkPaint::kStroke_Style);
            this->node()->setStrokeMiter(ParseDefault<SkScalar>(jpaint["ml"], 4.0f));

            static constexpr SkPaint::Join gJoins[] = {
                SkPaint::kMiter_Join,
                SkPaint::kRound_Join,
                SkPaint::kBevel_Join,
            };
            this->node()->setStrokeJoin(
                        gJoins[std::min<size_t>(ParseDefault<size_t>(jpaint["lj"], 1) - 1,
                                              SK_ARRAY_COUNT(gJoins) - 1)]);

            static constexpr SkPaint::Cap gCaps[] = {
                SkPaint::kButt_Cap,
                SkPaint::kRound_Cap,
                SkPaint::kSquare_Cap,
            };
            this->node()->setStrokeCap(
                        gCaps[std::min<size_t>(ParseDefault<size_t>(jpaint["lc"], 1) - 1,
                                             SK_ARRAY_COUNT(gCaps) - 1)]);
        }

        if (fShaderType == ShaderType::kColor) {
            this->bind(abuilder, jpaint["c"], fColor);
        }
    }

private:
    void onSync() override {
        this->node()->setOpacity(fOpacity * 0.01f);
        this->node()->setStrokeWidth(fStrokeWidth);

        if (fShaderType == ShaderType::kColor) {
            auto* color_node = static_cast<sksg::Color*>(this->node().get());
            color_node->setColor(fColor);
        }
    }

    enum class ShaderType { kColor, kGradient };

    const ShaderType fShaderType;

    VectorValue      fColor;
    ScalarValue      fOpacity     = 100,
                     fStrokeWidth = 1;

    using INHERITED = DiscardableAdapterBase<FillStrokeAdapter, sksg::PaintNode>;
};

class DashAdapter final : public DiscardableAdapterBase<DashAdapter, sksg::DashEffect> {
public:
    DashAdapter(const skjson::ArrayValue& jdash,
                const AnimationBuilder& abuilder,
                sk_sp<sksg::GeometryNode> geo)
        : INHERITED(sksg::DashEffect::Make(std::move(geo))) {
        SkASSERT(jdash.size() > 1);

        // The dash is encoded as an arbitrary number of intervals (alternating dash/gap),
        // plus a single trailing offset.  Each value can be animated independently.
        const auto interval_count = jdash.size() - 1;
        fIntervals.resize(interval_count, 0);

        for (size_t i = 0; i < jdash.size(); ++i) {
            if (const skjson::ObjectValue* jint = jdash[i]) {
                auto* target = i < interval_count
                        ? &fIntervals[i]
                        : &fOffset;
                this->bind(abuilder, (*jint)["v"], target);
            }
        }
    }

private:
    void onSync() override {
        this->node()->setPhase(fOffset);
        this->node()->setIntervals(fIntervals);
    }

    std::vector<ScalarValue> fIntervals;
    ScalarValue              fOffset = 0;

    using INHERITED = DiscardableAdapterBase<DashAdapter, sksg::DashEffect>;
};

} // namespace

sk_sp<sksg::PaintNode> ShapeBuilder::AttachFill(const skjson::ObjectValue& jpaint,
                                                const AnimationBuilder* abuilder,
                                                sk_sp<sksg::PaintNode> paint_node,
                                                sk_sp<AnimatablePropertyContainer> gradient) {
    return abuilder->attachDiscardableAdapter<FillStrokeAdapter>
            (jpaint,
             *abuilder,
             std::move(paint_node),
             std::move(gradient),
             FillStrokeAdapter::Type::kFill);
}

sk_sp<sksg::PaintNode> ShapeBuilder::AttachStroke(const skjson::ObjectValue& jpaint,
                                                  const AnimationBuilder* abuilder,
                                                  sk_sp<sksg::PaintNode> paint_node,
                                                  sk_sp<AnimatablePropertyContainer> gradient) {
    return abuilder->attachDiscardableAdapter<FillStrokeAdapter>
            (jpaint,
             *abuilder,
             std::move(paint_node),
             std::move(gradient),
             FillStrokeAdapter::Type::kStroke);
}

sk_sp<sksg::PaintNode> ShapeBuilder::AttachColorFill(const skjson::ObjectValue& jpaint,
                                                     const AnimationBuilder* abuilder) {
    auto color_node = sksg::Color::Make(SK_ColorBLACK);
    abuilder->dispatchColorProperty(color_node);

    return AttachFill(jpaint, abuilder, std::move(color_node));
}

sk_sp<sksg::PaintNode> ShapeBuilder::AttachColorStroke(const skjson::ObjectValue& jpaint,
                                                       const AnimationBuilder* abuilder) {
    auto color_node = sksg::Color::Make(SK_ColorBLACK);
    abuilder->dispatchColorProperty(color_node);

    return AttachStroke(jpaint, abuilder, std::move(color_node));
}

std::vector<sk_sp<sksg::GeometryNode>> ShapeBuilder::AdjustStrokeGeometry(
        const skjson::ObjectValue& jstroke,
        const AnimationBuilder* abuilder,
        std::vector<sk_sp<sksg::GeometryNode>>&& geos) {

    const skjson::ArrayValue* jdash = jstroke["d"];
    if (jdash && jdash->size() > 1) {
        for (size_t i = 0; i < geos.size(); ++i) {
            geos[i] = abuilder->attachDiscardableAdapter<DashAdapter>(
                          *jdash, *abuilder, std::move(geos[i]));
        }
    }

    return std::move(geos);
}

} // namespace internal
} // namespace skottie
