/***************************************************************************
*                                                                          *
*  Copyright (C) Golaem S.A.  All Rights Reserved.                         *
*                                                                          *
***************************************************************************/

#pragma once

#include "glmSDKAPI.h"
#include "glmMotionDefinitions.h"
#include "glmAbstractMotionBehavior.h"
#include "glmEntity.h"
#include "glmUserCallbackContext.h"
#include "glmGroundAdaptationBN.h"

namespace glm
{
    class AimAtBN;

    class GLM_SDK_API GroundAdaptBehavior : public AbstractMotionBehavior
    {
    public:
        //class GroundAdaptBehaviorData
        //{
        //public:

        //	GLM_CLASS_STAT_ID( glm::MemoryStatIds::Simulation)

        //	GroundAdaptBehaviorData();
        //	~GroundAdaptBehaviorData();

        //	Quaternion _previousBodyOri; // for orientation smoothing
        //};

        glm::GroundAdaptMode::Value _adaptationMode;
        GroundAdaptationBN::GroundEvaluation::Value _evaluationMode;
        float _maxLimbHeightDeltaRatio;
        float _maxSpineHeightDeltaRatio;
        float _raycastLengthFactor;
        float _footStrikeOffset = 0;
        float _footOffOffset = 0;
        float _footOffDuration = 0.2f;
        float _footLockCorrectionsStartRatio = 0.9f;
        float _footLockMaxFootRollCorrection = 90 * GLM_DEG_2_RAD;
        float _footLockMaxSnSCorrection = 1.1f;

        float _orientPelvisAttitudeOnGroundNormal = 0.f;
        float _orientPelvisBankOnGroundNormal = 0.f;
        float _orientPelvisAttitudeOnGroundContacts = 0.f;
        float _orientPelvisBankOnGroundContacts = 0.f;
        float _orientPelvisOnGroundMaxVelocity = 1.f;
        bool _compensatePelvisOriOnSupportChannels;
        bool _compensatePelvisOriOnOtherChannels;

        bool _includePhysicsWorld;
        AbstractGround* _physicsGround;
		bool _ownPhysicsGround;
        float _samplingRadius;
        int _samplingRayCount;
        float _nextFootprintRecomputationThresholdRatio;
        bool _doGroundAdaptationIK;

    private:
        GroundAdaptationBN* _groundAdaptBlendNode;
        UserCallbackContext* _callBackContext;

        //glm::Array< GroundAdaptBehaviorData > _groundAdaptData;
        glm::Array<Quaternion> _groundAdaptData;

    public:
        GLM_CLASS_STAT_ID( glm::MemoryStatIds::Simulation)

        GroundAdaptBehavior();
        virtual ~GroundAdaptBehavior();

        // type checking - value derived from this type
        virtual bool isThisType(const AbstractBehavior* value) const override;

    protected:
        // cloning
        friend class CloneFactory;
        inline virtual GroundAdaptBehavior* create() const override;

        // for entity data
        virtual void doAllocate(BehaviorGraph& graph) override;
        virtual void doDeallocate() override;
        virtual void doResize(BehaviorGraph& graph) override;

        virtual void doInit(BehaviorGraph& graph) override;
        virtual void doFinish(BehaviorGraph& graph) override;
        virtual void doStart(int64_t index, BehaviorGraph& graph) override;
        virtual void doUpdate(int64_t index, BehaviorGraph& graph, Time dt) override;
        virtual AbstractBehavior::ResultStatus::Value doStop(int64_t index, BehaviorGraph& graph, Time dt) override;

        virtual void doCallbackComputation(const UserCallbackContext& callbackContext, int64_t index, BehaviorGraph& graph, Time dt);
    };

    //-------------------------------------------------------------------------
    inline GroundAdaptBehavior* GroundAdaptBehavior::create() const
    {
        GroundAdaptBehavior* myNewGroundAdaptBehavior = GLM_NEW(GroundAdaptBehavior, myNewGroundAdaptBehavior, getClassMemoryStatId());
        return myNewGroundAdaptBehavior;
    }
} // namespace glm
