//
//  MoveActions.hpp
//  Meteor
//
//  Created by Cesar Parent on 27/08/2015.
//  Copyright © 2015 Cesar Parent. All rights reserved.
//

#ifndef MoveActions_hpp
#define MoveActions_hpp

#include "TimedActions.h"
#include "../Geometry.h"
#include "../Nodes.h"

NS_BEGIN

/*!
 * @internal
 * @brief           Move a node to a 2D location in its parent's coordinate system.
 */
class ActionMoveTo : public ActionTweenTo<vec2> {
    
public:
    ActionMoveTo(const vec2& destination, double duration) : ActionTweenTo(destination, duration) {}
    
    virtual ~ActionMoveTo() {};
    
protected:
    
    vec2
    get() override { return _target->position(); }
    
    void
    set(const vec2& value) override { _target->setPosition(value); }
};

// MARK: -
// MARK: Move To X

/*!
 * @internal
 * @brief       Move a node horizontally to a given X position
 */
class ActionMoveToX : public ActionTweenTo<float> {
public:
    
    ActionMoveToX(float to, double duration) : ActionTweenTo(to, duration) {}
    
    virtual ~ActionMoveToX() {}
    
protected:
    float
    get() override { return _target->position().x; }
    
    void
    set(const float& value) override { _target->setX(value); }
};

// MARK: -
// MARK: Move To Y

/*!
 * @internal
 * @brief       Move a node vertically to a given Y position
 */
class ActionMoveToY : public ActionTweenTo<float> {
public:
    
    ActionMoveToY(float to, double duration) : ActionTweenTo(to, duration) {}
    
    virtual ~ActionMoveToY() {}
    
protected:
    float
    get() override { return _target->position().y; }
    
    void
    set(const float& value) override { _target->setY(value); }
};

// MARK: -
// MARK: Fade To alpha

/*!
 * @internal
 * @brief       Fade a node to a given alpha value
 */
class ActionFadeTo : public ActionTweenTo<float> {
public:
    
    ActionFadeTo(float to, double duration) : ActionTweenTo(to, duration) {
        _to = clamp(_to, 0.f, 1.f);
    }
    
    virtual ~ActionFadeTo() {};
    
protected:
    
    float
    get() override { return _target->alpha(); }
    
    void
    set(const float& value) override { _target->setAlpha(value); }
    
};

// MARK: -
// MARK: Rotate To angle

/*!
 * @internal
 * @brief       Fade a node to a given alpha value
 */
class ActionRotateTo : public ActionTweenTo<float> {
public:
    
    ActionRotateTo(float to, double duration) : ActionTweenTo(to, duration) {}
    
    virtual ~ActionRotateTo() {};
    
protected:
    
    float
    get() override { return _target->rotation(); }
    
    void
    set(const float& value) override { _target->setRotation(value); }
    
};

// MARK: -
// MARK: Scale X To value

/*!
 * @internal
 * @brief       Scale a node to a given value along the X axis
 */
class ActionScaleXTo : public ActionTweenTo<float> {
public:
    
    ActionScaleXTo(float to, double duration) : ActionTweenTo(to, duration) {}
    
    virtual ~ActionScaleXTo() {};
    
protected:
    
    float
    get() override { return _target->xScale(); }
    
    void
    set(const float& value) override { _target->setXScale(value); }
};

// MARK: -
// MARK: Scale Y To value

/*!
 * @internal
 * @brief       Scale a node to a given value along the Y axis
 */
class ActionScaleYTo : public ActionTweenTo<float> {
public:
    
    ActionScaleYTo(float to, double duration) : ActionTweenTo(to, duration) {}
    
    virtual ~ActionScaleYTo() {};
    
protected:
    
    float
    get() override { return _target->yScale(); }
    
    void
    set(const float& value) override { _target->setYScale(value); }
};


// MARK: -
// MARK: Move by vector

/*!
 * @internal
 * @brief           Move a node along a 2D vector in its parent's coordinate system.
 */
class ActionMoveBy : public ActionTweenBy<vec2> {
    
public:
    ActionMoveBy(const vec2& offset, double duration) : ActionTweenBy(offset, duration) {}
    
    virtual ~ActionMoveBy() {};
    
protected:
    
    vec2
    get() override { return _target->position(); }
    
    void
    set(const vec2& value) override { _target->setPosition(value); }
};

// MARK: -
// MARK: Rotate by an angle


class ActionRotateBy : public ActionTweenBy<float> {
public:
    
    ActionRotateBy(float offset, double duration) : ActionTweenBy(offset, duration) {}
    
    virtual ~ActionRotateBy() {};
    
protected:
    
    float
    get() override { return _target->rotation(); }
    
    void
    set(const float& value) override { _target->setRotation(value); }
};

// MARK: -
// MARK: ScaleXBy

class ActionScaleBy : public ActionTweenBy<vec2> {
public:
    
    ActionScaleBy(const vec2& offset, double duration) : ActionTweenBy(offset, duration) {}
    
    virtual ~ActionScaleBy() {};
    
protected:
    
    vec2
    get() override { return {_target->xScale(), _target->yScale()}; }
    
    void
    set(const vec2& value) override { _target->setXScale(value.x); _target->setYScale(value.y); }
};

// MARK: -
// MARK: Fade by alpha fraction

class ActionFadeBy : public ActionTweenBy<float> {
public:
    
    ActionFadeBy(float offset, double duration) : ActionTweenBy(offset, duration) {}
    
    virtual ~ActionFadeBy() {};
    
protected:
    
    float
    get() override { return _target->alpha(); }
    
    void
    set(const float& value) override { _target->setAlpha(value); }
};



NS_END

#endif /* MoveActions_hpp */
