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

#pragma once

#include "glmSDKAPI.h"

#include "glmApex.h"
#include "glmApexUtils.h"
#include "glmAbstractUserBehavior.h"

namespace glm
{
	class CharacterSkinMeshesInterface;
    class PhysicsRigidBody;
    struct ClothingActor;
    struct ClothingAssetWithCacheData;

    // Send commands to the physics context to start/stop simulation APEX clothes
    class GLM_SDK_API BehaviorApexCloth : public AbstractUserBehavior
    {

    public:
        class PerEntityData
        {
        public:
            Vector3 _windVelocityNoise; // per entity noise to add to the behavior _windVelocity. The noise is constant for the whoel simulation, but dfferent between entities
            float _currentMaxDistanceScale;
            glm::Array<glm::ClothingActor*> _clothingActors;
            float _additionalClothScale = 1.f;

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

            inline PerEntityData();
        };

        glm::Array<glm::GlmString> _clothingAssetsNames; //To be configured by the user of the behavior before init
        glm::Array<PhysicsRigidBody*> _rigidBodiesColliders;
        float _windAdaption;
        Vector3 _windVelocity;
        ICallBack::SP _windVelocityCallback;
        //unsigned int _entityId;	//not used internally, just used for user output on error messages
        float _startingDuration;
        float _stoppingDuration;
        bool _freezeOnStop;
		int _frozenClothBoneBinding;

		bool _enableOverrideApexMaterial;
        glm::ApexMaterial _overrideApexMaterial;
		float _additionalGravityScale;
        bool _additionalSupportScale = true;

        CharacterSkinMeshesInterface* _skinMesh; //The skinMesh is used to initialize an apex cloth when the .apx file does not exist. It's not mandatory

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

        BehaviorApexCloth();
        inline virtual ~BehaviorApexCloth();

        void setWindVelocityCallback(ICallBack* callback);
        void setWindVelocityNoise(int64_t index, const Vector3& windVelocityNoise);
        void setAdditionalClothScale(int64_t index, float additionalClothScale);

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

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

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

        glm::Array<ClothingAssetWithCacheData*> _clothingAssets; //will be set the same size than _clothAssetsNames at init, and filled with pointers to the correct assets (loaded at init time)
        glm::Array<PerEntityData> _clothBehaviorPerEntityData;
    };

    //-------------------------------------------------------------------------
    inline BehaviorApexCloth::PerEntityData::PerEntityData()
        : _windVelocityNoise(0, 0, 0)
        , _currentMaxDistanceScale(0)
    {
    }

    //-------------------------------------------------------------------------
    inline BehaviorApexCloth::~BehaviorApexCloth()
    {
    }

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