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

#include "SkAnimTimer.h"
#include "SkCanvas.h"
#include "SkCubicMap.h"
#include "SkMakeUnique.h"
#include "SkSGColor.h"
#include "SkSGDraw.h"
#include "SkSGGroup.h"
#include "SkSGPlane.h"
#include "SkSGRect.h"
#include "SkSGRenderNode.h"
#include "SkSGScene.h"
#include "SkSGText.h"
#include "SkSGTransform.h"
#include "SkTypeface.h"

#include <cmath>

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);
    }

    std::unique_ptr<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 skstd::make_unique<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 override {
        SkAutoCanvasRestore acr(canvas, true);
        canvas->clipRect(SkRect::Make(fSlide->getDimensions()), true);
        fSlide->draw(canvas);
    }

private:
    void tick(SkMSec t) {
        fSlide->animate(SkAnimTimer(0, t * 1e6, SkAnimTimer::kRunning_State));
        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::Transform> fTransform;
    SkRect                 fRect;
};

class SlideDir::FocusController final : public sksg::Animator {
public:
    FocusController(const SlideDir* dir, const SkRect& focusRect)
        : fDir(dir)
        , fRect(focusRect)
        , fTarget(nullptr)
        , fState(State::kIdle) {
        fMap.setPts(kFocusCtrl1, kFocusCtrl0);

        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->fTransform);
        fDir->fRoot->addChild(fShade);
        fDir->fRoot->addChild(fTarget->fTransform);

        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);

        SkTSwap(fM0, fM1);
        SkTSwap(fOpacity0, fOpacity1);

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

    bool onMouse(SkScalar x, SkScalar y, sk_app::Window::InputState state, uint32_t 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->fTransform->getMatrix()->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>, true>&& 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->setFlags(SkPaint::kAntiAlias_Flag);
    text->setSize(size);
    text->setAlign(SkPaint::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 = 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));
        auto slideTransform = sksg::Transform::Make(std::move(slideGrp), slideMatrix);

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

        fRoot->addChild(slideTransform);
        fRecs.push_back({ slide, slideTransform, 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(const SkAnimTimer& timer) {
    if (fTimeBase == 0) {
        // Reset the animation time.
        fTimeBase = timer.msec();
    }

    const auto t = timer.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, sk_app::Window::InputState state,
                       uint32_t modifiers) {
    if (state == sk_app::Window::kMove_InputState || 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 sk_app::Window::kDown_InputState:
        fTrackingCell = cell;
        fTrackingPos = SkPoint::Make(x, y);
        break;
    case sk_app::Window::kUp_InputState:
        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;
}
