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

#include "include/core/SkCanvas.h"
#include "modules/sksg/include/SkSGInvalidationController.h"

namespace skottie {
namespace internal {

sk_sp<MotionBlurEffect> MotionBlurEffect::Make(sk_sp<sksg::Animator> animator,
                                               sk_sp<sksg::RenderNode> child,
                                               size_t samples_per_frame,
                                               float shutter_angle, float shutter_phase) {
    if (!samples_per_frame || shutter_angle <= 0) {
        return nullptr;
    }

    // shutter_angle is [   0 .. 720], mapped to [ 0 .. 2] (frame space)
    // shutter_phase is [-360 .. 360], mapped to [-1 .. 1] (frame space)
    const auto samples_duration = shutter_angle / 360,
                          phase = shutter_phase / 360,
                             dt = samples_duration / (samples_per_frame - 1);

    return sk_sp<MotionBlurEffect>(new MotionBlurEffect(std::move(animator),
                                                        std::move(child),
                                                        samples_per_frame,
                                                        phase, dt));
}

MotionBlurEffect::MotionBlurEffect(sk_sp<sksg::Animator> animator,
                                   sk_sp<sksg::RenderNode> child,
                                   size_t samples, float phase, float dt)
    : INHERITED({std::move(child)})
    , fAnimator(std::move(animator))
    , fSampleCount(samples)
    , fPhase(phase)
    , fDT(dt) {}

const sksg::RenderNode* MotionBlurEffect::onNodeAt(const SkPoint&) const {
    return nullptr;
}

SkRect MotionBlurEffect::onRevalidate(sksg::InvalidationController*, const SkMatrix& ctm) {
    SkASSERT(this->children().size() == 1ul);
    const auto& child = this->children()[0];

    auto bounds = SkRect::MakeEmpty();

    // Use a local inval controller to suppress descendent invals during sampling
    // (superseded by our local inval bounds).
    sksg::InvalidationController ic;

    auto t = fT + fPhase;

    for (size_t i = 0; i < fSampleCount; ++i) {
        fAnimator->tick(t);
        t += fDT;

        if (!child->isVisible()) {
            continue;
        }

        bounds.join(child->revalidate(&ic, ctm));
    }

    return bounds;
}

void MotionBlurEffect::onRender(SkCanvas* canvas, const RenderContext* ctx) const {
    SkASSERT(this->children().size() == 1ul);
    const auto& child = this->children()[0];

    SkAutoCanvasRestore acr(canvas, false);

    // Accumulate in F16 for more precision.
    canvas->saveLayer(SkCanvas::SaveLayerRec(&this->bounds(), nullptr, SkCanvas::kF16ColorType));

    const auto frame_alpha = 1.0f / fSampleCount;

    // Depending on whether we can defer frame blending,
    // use a local (deferred) RenderContext or an explicit layer for frame/content rendering.
    ScopedRenderContext frame_ctx(canvas, ctx);
    SkPaint             frame_paint;

    const auto isolate_frames = ctx->fBlendMode != SkBlendMode::kSrcOver;
    if (isolate_frames) {
        frame_paint.setAlphaf(frame_alpha);
        frame_paint.setBlendMode(SkBlendMode::kPlus);
    } else {
        frame_ctx = frame_ctx.modulateOpacity(frame_alpha)
                             .modulateBlendMode(SkBlendMode::kPlus);
    }

    sksg::InvalidationController ic;

    auto t = fT + fPhase;

    for (size_t i = 0; i < fSampleCount; ++i) {
        fAnimator->tick(t);
        t += fDT;

        if (!child->isVisible()) {
            continue;
        }

        child->revalidate(&ic, canvas->getTotalMatrix());

        SkAutoCanvasRestore acr(canvas, false);
        if (isolate_frames) {
            canvas->saveLayer(nullptr, &frame_paint);
        }

        child->render(canvas, frame_ctx);
    }
}

} // namespace internal
} // namespace skottie
