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

#include "tools/viewer/SlideDir.h"

#include "include/core/SkCanvas.h"
#include "include/core/SkCubicMap.h"
#include "include/core/SkTypeface.h"
#include "modules/sksg/include/SkSGDraw.h"
#include "modules/sksg/include/SkSGGroup.h"
#include "modules/sksg/include/SkSGPaint.h"
#include "modules/sksg/include/SkSGPlane.h"
#include "modules/sksg/include/SkSGRect.h"
#include "modules/sksg/include/SkSGRenderNode.h"
#include "modules/sksg/include/SkSGScene.h"
#include "modules/sksg/include/SkSGText.h"
#include "modules/sksg/include/SkSGTransform.h"
#include "src/core/SkMakeUnique.h"
#include "tools/timer/TimeUtils.h"

#include <cmath>
#include <utility>

namespace {

static constexpr float  kAspectRatio   = 1.5f;
static constexpr float  kLabelSize     = 12.0f;
static constexpr SkSize kPadding       = { 12.0f , 24.0f };

static constexpr float   kFocusDuration = 500;
static constexpr SkSize  kFocusInset    = { 100.0f, 100.0f };
static constexpr SkPoint kFocusCtrl0    = {   0.3f,   1.0f };
static constexpr SkPoint kFocusCtrl1    = {   0.0f,   1.0f };
static constexpr SkColor kFocusShade    = 0xa0000000;

// TODO: better unfocus binding?
static constexpr SkUnichar kUnfocusKey = ' ';

class SlideAdapter final : public sksg::RenderNode {
public:
    explicit SlideAdapter(sk_sp<Slide> slide)
        : fSlide(std::move(slide)) {
        SkASSERT(fSlide);
    }

    sk_sp<sksg::Animator> makeForwardingAnimator() {
        // Trivial sksg::Animator -> skottie::Animation tick adapter
        class ForwardingAnimator final : public sksg::Animator {
        public:
            explicit ForwardingAnimator(sk_sp<SlideAdapter> adapter)
                : fAdapter(std::move(adapter)) {}

        protected:
            void onTick(float t) override {
                fAdapter->tick(SkScalarRoundToInt(t));
            }

        private:
            sk_sp<SlideAdapter> fAdapter;
        };

        return sk_make_sp<ForwardingAnimator>(sk_ref_sp(this));
    }

protected:
    SkRect onRevalidate(sksg::InvalidationController* ic, const SkMatrix& ctm) override {
        const auto isize = fSlide->getDimensions();
        return SkRect::MakeIWH(isize.width(), isize.height());
    }

    void onRender(SkCanvas* canvas, const RenderContext* ctx) const override {
        SkAutoCanvasRestore acr(canvas, true);
        canvas->clipRect(SkRect::Make(fSlide->getDimensions()), true);

        // TODO: commit the context?
        fSlide->draw(canvas);
    }

    const RenderNode* onNodeAt(const SkPoint&) const override { return nullptr; }

private:
    void tick(SkMSec t) {
        fSlide->animate(t * 1e6);
        this->invalidate();
    }

    const sk_sp<Slide> fSlide;

    using INHERITED = sksg::RenderNode;
};

SkMatrix SlideMatrix(const sk_sp<Slide>& slide, const SkRect& dst) {
    const auto slideSize = slide->getDimensions();
    return SkMatrix::MakeRectToRect(SkRect::MakeIWH(slideSize.width(), slideSize.height()),
                                    dst,
                                    SkMatrix::kCenter_ScaleToFit);
}

} // namespace

struct SlideDir::Rec {
    sk_sp<Slide>                  fSlide;
    sk_sp<sksg::RenderNode>       fSlideRoot;
    sk_sp<sksg::Matrix<SkMatrix>> fMatrix;
    SkRect                        fRect;
};

class SlideDir::FocusController final : public sksg::Animator {
public:
    FocusController(const SlideDir* dir, const SkRect& focusRect)
        : fDir(dir)
        , fRect(focusRect)
        , fTarget(nullptr)
        , fMap(kFocusCtrl1, kFocusCtrl0)
        , fState(State::kIdle) {
        fShadePaint = sksg::Color::Make(kFocusShade);
        fShade = sksg::Draw::Make(sksg::Plane::Make(), fShadePaint);
    }

    bool hasFocus() const { return fState == State::kFocused; }

    void startFocus(const Rec* target) {
        if (fState != State::kIdle)
            return;

        fTarget = target;

        // Move the shade & slide to front.
        fDir->fRoot->removeChild(fTarget->fSlideRoot);
        fDir->fRoot->addChild(fShade);
        fDir->fRoot->addChild(fTarget->fSlideRoot);

        fM0 = SlideMatrix(fTarget->fSlide, fTarget->fRect);
        fM1 = SlideMatrix(fTarget->fSlide, fRect);

        fOpacity0 = 0;
        fOpacity1 = 1;

        fTimeBase = 0;
        fState = State::kFocusing;

        // Push initial state to the scene graph.
        this->onTick(fTimeBase);
    }

    void startUnfocus() {
        SkASSERT(fTarget);

        using std::swap;
        swap(fM0, fM1);
        swap(fOpacity0, fOpacity1);

        fTimeBase = 0;
        fState = State::kUnfocusing;
    }

    bool onMouse(SkScalar x, SkScalar y, InputState state, ModifierKey modifiers) {
        SkASSERT(fTarget);

        if (!fRect.contains(x, y)) {
            this->startUnfocus();
            return true;
        }

        // Map coords to slide space.
        const auto xform = SkMatrix::MakeRectToRect(fRect,
                                                    SkRect::MakeSize(fDir->fWinSize),
                                                    SkMatrix::kCenter_ScaleToFit);
        const auto pt = xform.mapXY(x, y);

        return fTarget->fSlide->onMouse(pt.x(), pt.y(), state, modifiers);
    }

    bool onChar(SkUnichar c) {
        SkASSERT(fTarget);

        return fTarget->fSlide->onChar(c);
    }

protected:
    void onTick(float t) {
        if (!this->isAnimating())
            return;

        if (!fTimeBase) {
            fTimeBase = t;
        }

        const auto rel_t = (t - fTimeBase) / kFocusDuration,
                   map_t = SkTPin(fMap.computeYFromX(rel_t), 0.0f, 1.0f);

        SkMatrix m;
        for (int i = 0; i < 9; ++i) {
            m[i] = fM0[i] + map_t * (fM1[i] - fM0[i]);
        }

        SkASSERT(fTarget);
        fTarget->fMatrix->setMatrix(m);

        const auto shadeOpacity = fOpacity0 + map_t * (fOpacity1 - fOpacity0);
        fShadePaint->setOpacity(shadeOpacity);

        if (rel_t < 1)
            return;

        switch (fState) {
        case State::kFocusing:
            fState = State::kFocused;
            break;
        case State::kUnfocusing:
            fState  = State::kIdle;
            fDir->fRoot->removeChild(fShade);
            break;

        case State::kIdle:
        case State::kFocused:
            SkASSERT(false);
            break;
        }
    }

private:
    enum class State {
        kIdle,
        kFocusing,
        kUnfocusing,
        kFocused,
    };

    bool isAnimating() const { return fState == State::kFocusing || fState == State::kUnfocusing; }

    const SlideDir*         fDir;
    const SkRect            fRect;
    const Rec*              fTarget;

    SkCubicMap              fMap;
    sk_sp<sksg::RenderNode> fShade;
    sk_sp<sksg::PaintNode>  fShadePaint;

    SkMatrix        fM0       = SkMatrix::I(),
                    fM1       = SkMatrix::I();
    float           fOpacity0 = 0,
                    fOpacity1 = 1,
                    fTimeBase = 0;
    State           fState    = State::kIdle;

    using INHERITED = sksg::Animator;
};

SlideDir::SlideDir(const SkString& name, SkTArray<sk_sp<Slide>>&& slides, int columns)
    : fSlides(std::move(slides))
    , fColumns(columns) {
    fName = name;
}

static sk_sp<sksg::RenderNode> MakeLabel(const SkString& txt,
                                         const SkPoint& pos,
                                         const SkMatrix& dstXform) {
    const auto size = kLabelSize / std::sqrt(dstXform.getScaleX() * dstXform.getScaleY());
    auto text = sksg::Text::Make(nullptr, txt);
    text->setEdging(SkFont::Edging::kAntiAlias);
    text->setSize(size);
    text->setAlign(SkTextUtils::kCenter_Align);
    text->setPosition(pos + SkPoint::Make(0, size));

    return sksg::Draw::Make(std::move(text), sksg::Color::Make(SK_ColorBLACK));
}

void SlideDir::load(SkScalar winWidth, SkScalar winHeight) {
    // Build a global scene using transformed animation fragments:
    //
    // [Group(root)]
    //     [Transform]
    //         [Group]
    //             [AnimationWrapper]
    //             [Draw]
    //                 [Text]
    //                 [Color]
    //     [Transform]
    //         [Group]
    //             [AnimationWrapper]
    //             [Draw]
    //                 [Text]
    //                 [Color]
    //     ...
    //

    fWinSize = SkSize::Make(winWidth, winHeight);
    const auto  cellWidth =  winWidth / fColumns;
    fCellSize = SkSize::Make(cellWidth, cellWidth / kAspectRatio);

    sksg::AnimatorList sceneAnimators;
    fRoot = sksg::Group::Make();

    for (int i = 0; i < fSlides.count(); ++i) {
        const auto& slide     = fSlides[i];
        slide->load(winWidth, winHeight);

        const auto  slideSize = slide->getDimensions();
        const auto  cell      = SkRect::MakeXYWH(fCellSize.width()  * (i % fColumns),
                                                 fCellSize.height() * (i / fColumns),
                                                 fCellSize.width(),
                                                 fCellSize.height()),
                    slideRect = cell.makeInset(kPadding.width(), kPadding.height());

        auto slideMatrix = sksg::Matrix<SkMatrix>::Make(SlideMatrix(slide, slideRect));
        auto adapter     = sk_make_sp<SlideAdapter>(slide);
        auto slideGrp    = sksg::Group::Make();
        slideGrp->addChild(sksg::Draw::Make(sksg::Rect::Make(SkRect::MakeIWH(slideSize.width(),
                                                                             slideSize.height())),
                                            sksg::Color::Make(0xfff0f0f0)));
        slideGrp->addChild(adapter);
        slideGrp->addChild(MakeLabel(slide->getName(),
                                     SkPoint::Make(slideSize.width() / 2, slideSize.height()),
                                     slideMatrix->getMatrix()));
        auto slideRoot = sksg::TransformEffect::Make(std::move(slideGrp), slideMatrix);

        sceneAnimators.push_back(adapter->makeForwardingAnimator());

        fRoot->addChild(slideRoot);
        fRecs.push_back({ slide, slideRoot, slideMatrix, slideRect });
    }

    fScene = sksg::Scene::Make(fRoot, std::move(sceneAnimators));

    const auto focusRect = SkRect::MakeSize(fWinSize).makeInset(kFocusInset.width(),
                                                                kFocusInset.height());
    fFocusController = skstd::make_unique<FocusController>(this, focusRect);
}

void SlideDir::unload() {
    for (const auto& slide : fSlides) {
        slide->unload();
    }

    fRecs.reset();
    fScene.reset();
    fFocusController.reset();
    fRoot.reset();
    fTimeBase = 0;
}

SkISize SlideDir::getDimensions() const {
    return SkSize::Make(fWinSize.width(),
                        fCellSize.height() * (1 + (fSlides.count() - 1) / fColumns)).toCeil();
}

void SlideDir::draw(SkCanvas* canvas) {
    fScene->render(canvas);
}

bool SlideDir::animate(double nanos) {
    SkMSec msec = TimeUtils::NanosToMSec(nanos);
    if (fTimeBase == 0) {
        // Reset the animation time.
        fTimeBase = msec;
    }

    const auto t = msec - fTimeBase;
    fScene->animate(t);
    fFocusController->tick(t);

    return true;
}

bool SlideDir::onChar(SkUnichar c) {
    if (fFocusController->hasFocus()) {
        if (c == kUnfocusKey) {
            fFocusController->startUnfocus();
            return true;
        }
        return fFocusController->onChar(c);
    }

    return false;
}

bool SlideDir::onMouse(SkScalar x, SkScalar y, InputState state,
                       ModifierKey modifiers) {
    modifiers &= ~ModifierKey::kFirstPress;
    if (state == InputState::kMove || skstd::Any(modifiers))
        return false;

    if (fFocusController->hasFocus()) {
        return fFocusController->onMouse(x, y, state, modifiers);
    }

    const auto* cell = this->findCell(x, y);
    if (!cell)
        return false;

    static constexpr SkScalar kClickMoveTolerance = 4;

    switch (state) {
    case InputState::kDown:
        fTrackingCell = cell;
        fTrackingPos = SkPoint::Make(x, y);
        break;
    case InputState::kUp:
        if (cell == fTrackingCell &&
            SkPoint::Distance(fTrackingPos, SkPoint::Make(x, y)) < kClickMoveTolerance) {
            fFocusController->startFocus(cell);
        }
        break;
    default:
        break;
    }

    return false;
}

const SlideDir::Rec* SlideDir::findCell(float x, float y) const {
    // TODO: use SG hit testing instead of layout info?
    const auto size = this->getDimensions();
    if (x < 0 || y < 0 || x >= size.width() || y >= size.height()) {
        return nullptr;
    }

    const int col = static_cast<int>(x / fCellSize.width()),
              row = static_cast<int>(y / fCellSize.height()),
              idx = row * fColumns + col;

    return idx < fRecs.count() ? &fRecs[idx] : nullptr;
}
