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

#ifndef SkottieTransform_DEFINED
#define SkottieTransform_DEFINED

#include "include/core/SkM44.h"
#include "include/core/SkMatrix.h"
#include "include/core/SkPoint.h"
#include "modules/skottie/src/Adapter.h"
#include "modules/skottie/src/SkottieValue.h"
#include "modules/sksg/include/SkSGTransform.h"

#include <utility>

namespace skjson {
class ObjectValue;

}  // namespace skjson

namespace skottie {
namespace internal {
class AnimationBuilder;

class TransformAdapter2D final : public DiscardableAdapterBase<TransformAdapter2D,
                                                               sksg::Matrix<SkMatrix>> {
public:
    TransformAdapter2D(const AnimationBuilder&,
                       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 = false);
    ~TransformAdapter2D() override;

    // Accessors needed for public property APIs.
    // TODO: introduce a separate public type.
    SkPoint getAnchorPoint() const;
    void    setAnchorPoint(const SkPoint&);

    SkPoint getPosition() const;
    void    setPosition(const SkPoint&);

    SkVector getScale() const;
    void     setScale(const SkVector&);

    float getRotation() const  { return fRotation; }
    void  setRotation(float r);

    float getSkew() const   { return fSkew; }
    void  setSkew(float sk);

    float getSkewAxis() const    { return fSkewAxis; }
    void  setSkewAxis(float sa );

    SkMatrix totalMatrix() const;

private:
    void onSync() override;

    Vec2Value   fAnchorPoint = {   0,   0 },
                fPosition    = {   0,   0 },
                fScale       = { 100, 100 };
    ScalarValue fRotation    = 0,
                fSkew        = 0,
                fSkewAxis    = 0,
                fOrientation = 0; // additional rotation component controlled by auto-orient

    using INHERITED = DiscardableAdapterBase<TransformAdapter2D, sksg::Matrix<SkMatrix>>;
};

class TransformAdapter3D : public DiscardableAdapterBase<TransformAdapter3D, sksg::Matrix<SkM44>> {
public:
    TransformAdapter3D(const skjson::ObjectValue&, const AnimationBuilder&);
    ~TransformAdapter3D() override;

    virtual SkM44 totalMatrix() const;

protected:
    SkV3 anchor_point() const;
    SkV3 position() const;
    SkV3 rotation() const;

private:
    void onSync() final;

    VectorValue fAnchorPoint,
                fPosition,
                fOrientation,
                fScale = { 100, 100, 100 };
    ScalarValue fRx = 0,
                fRy = 0,
                fRz = 0;

    using INHERITED = DiscardableAdapterBase<TransformAdapter3D, sksg::Matrix<SkM44>>;
};

} // namespace internal
} // namespace skottie

#endif // SkottieTransform_DEFINED
