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

#include "modules/skottie/src/SkottieJson.h"
#include "modules/skottie/src/SkottiePriv.h"
#include "modules/sksg/include/SkSGTransform.h"

namespace skottie {
namespace internal {

TransformAdapter2D::TransformAdapter2D(const AnimationBuilder& abuilder,
                                       const skjson::ObjectValue* janchor_point,
                                       const skjson::ObjectValue* jposition,
                                       const skjson::ObjectValue* jscale,
                                       const skjson::ObjectValue* jrotation,
                                       const skjson::ObjectValue* jskew,
                                       const skjson::ObjectValue* jskew_axis,
                                       bool auto_orient)
    : INHERITED(sksg::Matrix<SkMatrix>::Make(SkMatrix::I())) {

    this->bind(abuilder, janchor_point, fAnchorPoint);
    this->bind(abuilder, jscale       , fScale);
    this->bind(abuilder, jrotation    , fRotation);
    this->bind(abuilder, jskew        , fSkew);
    this->bind(abuilder, jskew_axis   , fSkewAxis);

    this->bindAutoOrientable(abuilder, jposition, &fPosition, auto_orient ? &fOrientation
                                                                          : nullptr);
}

TransformAdapter2D::~TransformAdapter2D() {}

void TransformAdapter2D::onSync() {
    this->node()->setMatrix(this->totalMatrix());
}

SkMatrix TransformAdapter2D::totalMatrix() const {
    // TODO: skew
    return SkMatrix::Translate(fPosition.x, fPosition.y)
         * SkMatrix::RotateDeg(fRotation + fOrientation)
         * SkMatrix::Scale    (fScale.x / 100, fScale.y / 100) // 100% based
         * SkMatrix::Translate(-fAnchorPoint.x, -fAnchorPoint.y);
}

SkPoint TransformAdapter2D::getAnchorPoint() const {
    return { fAnchorPoint.x, fAnchorPoint.y };
}

void TransformAdapter2D::setAnchorPoint(const SkPoint& ap) {
    fAnchorPoint = { ap.x(), ap.y() };
    this->onSync();
}

SkPoint TransformAdapter2D::getPosition() const {
    return { fPosition.x, fPosition.y };
}

void TransformAdapter2D::setPosition(const SkPoint& p) {
    fPosition = { p.x(), p.y() };
    this->onSync();
}

SkVector TransformAdapter2D::getScale() const {
    return { fScale.x, fScale.y };
}

void TransformAdapter2D::setScale(const SkVector& s) {
    fScale = { s.x(), s.y() };
    this->onSync();
}

void TransformAdapter2D::setRotation(float r) {
    fRotation = r;
    this->onSync();
}

void TransformAdapter2D::setSkew(float sk) {
    fSkew = sk;
    this->onSync();
}

void TransformAdapter2D::setSkewAxis(float sa) {
    fSkewAxis = sa;
    this->onSync();
}

sk_sp<sksg::Transform> AnimationBuilder::attachMatrix2D(const skjson::ObjectValue& jtransform,
                                                        sk_sp<sksg::Transform> parent,
                                                        bool auto_orient) const {
    const auto* jrotation = &jtransform["r"];
    if (jrotation->is<skjson::NullValue>()) {
        // Some 2D rotations are disguised as 3D...
        jrotation = &jtransform["rz"];
    }

    auto adapter = TransformAdapter2D::Make(*this,
                                            jtransform["a"],
                                            jtransform["p"],
                                            jtransform["s"],
                                            *jrotation,
                                            jtransform["sk"],
                                            jtransform["sa"],
                                            auto_orient);
    SkASSERT(adapter);

    const auto dispatched = this->dispatchTransformProperty(adapter);

    if (adapter->isStatic()) {
        if (!dispatched && adapter->totalMatrix().isIdentity()) {
            // The transform has no observable effects - we can discard.
            return parent;
        }
        adapter->seek(0);
    } else {
        fCurrentAnimatorScope->push_back(adapter);
    }

    return sksg::Transform::MakeConcat(std::move(parent), adapter->node());
}

TransformAdapter3D::TransformAdapter3D(const skjson::ObjectValue& jtransform,
                                       const AnimationBuilder& abuilder)
    : INHERITED(sksg::Matrix<SkM44>::Make(SkM44())) {

    this->bind(abuilder, jtransform["a"], fAnchorPoint);
    this->bind(abuilder, jtransform["p"], fPosition);
    this->bind(abuilder, jtransform["s"], fScale);

    // Axis-wise rotation and orientation are mapped to the same rotation property (3D rotation).
    // The difference is in how they get interpolated (scalar/decomposed vs. vector).
    this->bind(abuilder, jtransform["rx"], fRx);
    this->bind(abuilder, jtransform["ry"], fRy);
    this->bind(abuilder, jtransform["rz"], fRz);
    this->bind(abuilder, jtransform["or"], fOrientation);
}

TransformAdapter3D::~TransformAdapter3D() = default;

void TransformAdapter3D::onSync() {
    this->node()->setMatrix(this->totalMatrix());
}

SkV3 TransformAdapter3D::anchor_point() const {
    return fAnchorPoint;
}

SkV3 TransformAdapter3D::position() const {
    return fPosition;
}

SkV3 TransformAdapter3D::rotation() const {
    // orientation and axis-wise rotation map onto the same property.
    return static_cast<SkV3>(fOrientation) + SkV3{ fRx, fRy, fRz };
}

SkM44 TransformAdapter3D::totalMatrix() const {
    const auto anchor_point = this->anchor_point(),
               position     = this->position(),
               scale        = static_cast<SkV3>(fScale),
               rotation     = this->rotation();

    return SkM44::Translate(position.x, position.y, position.z)
         * SkM44::Rotate({ 1, 0, 0 }, SkDegreesToRadians(rotation.x))
         * SkM44::Rotate({ 0, 1, 0 }, SkDegreesToRadians(rotation.y))
         * SkM44::Rotate({ 0, 0, 1 }, SkDegreesToRadians(rotation.z))
         * SkM44::Scale(scale.x / 100, scale.y / 100, scale.z / 100)
         * SkM44::Translate(-anchor_point.x, -anchor_point.y, -anchor_point.z);
}

sk_sp<sksg::Transform> AnimationBuilder::attachMatrix3D(const skjson::ObjectValue& jtransform,
                                                        sk_sp<sksg::Transform> parent,
                                                        bool /*TODO: auto_orient*/) const {
    auto adapter = TransformAdapter3D::Make(jtransform, *this);
    SkASSERT(adapter);

    if (adapter->isStatic()) {
        // TODO: SkM44::isIdentity?
        if (adapter->totalMatrix() == SkM44()) {
            // The transform has no observable effects - we can discard.
            return parent;
        }
        adapter->seek(0);
    } else {
        fCurrentAnimatorScope->push_back(adapter);
    }

    return sksg::Transform::MakeConcat(std::move(parent), adapter->node());
}

} // namespace internal
} // namespace skottie
