/*Copyright (C) 2010-2023 Duncan Deveaux

This file is part of Hikou no mizu.

Hikou no mizu is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

Hikou no mizu is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with Hikou no mizu.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef DEF_PHYSICS_ROUTINES
#define DEF_PHYSICS_ROUTINES

#include <vector>

class PhysicsObject;
struct Box;

enum class Axis { Horizontal, Vertical };

struct ParabolaStep
{
    ParabolaStep() : positionDelta(0.f), velocityDelta(0.f) {}
    float positionDelta;
    float velocityDelta;
};

namespace PhysicsRoutines
{
    void soustractVectors(std::vector<PhysicsObject*> &dst,
                          const std::vector<PhysicsObject*> &src);

    void sortObjectsByX(std::vector<PhysicsObject*> &objects, int checkedSide);
    void sortObjectsByY(std::vector<PhysicsObject*> &objects, int checkedSide);

    bool containsFixedObject(const std::vector<PhysicsObject*> &objects);

    ParabolaStep computeParabolaStep(float velocity,
                                     float acceleration, float timeDelta);

    //PhysicsObjects sorting functors
    struct SortByXPos
    {
        explicit SortByXPos(int checkedSide = 0);
        bool operator() (const PhysicsObject *lhs,
                         const PhysicsObject *rhs) const;

        int side;
    };

    struct SortByYPos
    {
        explicit SortByYPos(int checkedSide = 0);
        bool operator() (const PhysicsObject *lhs,
                         const PhysicsObject *rhs) const;

        int side;
    };

    struct FindFixed
    {
        bool operator() (const PhysicsObject *obj) const;
    };

    struct BoxView1D
    {
        explicit BoxView1D(Axis axis);

        float position(const Box &box) const;
        float size(const Box &box) const;
        float bound(const Box &box) const; ///< position() + size()

        /// Shrink the width or the height (depending on the axis)
        /// by \p amount on both sides
        Box shrink(const Box &box, float amount) const;

        void setPosition(Box &box, float position) const;
        void setSize(Box &box, float size) const;

        Axis axis;
    };
}

#endif
