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

#pragma once

#include "glmSDKAPI.h"
#include <glmAbstractUserBehavior.h>
#include <glmGroup.h>

namespace glm
{
    // Changes the formation of a group entity
    class GLM_SDK_API SetFormationBehavior : public AbstractUserBehavior
    {
    public:
        class GLM_SDK_API SetFormationBehaviorData
        {
        public:
            bool _formationSet;
            float _savedAngularSpeed;

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

            SetFormationBehaviorData();
            ~SetFormationBehaviorData();
        };

    private:
        glm::Array<SetFormationBehaviorData> _setFormationBehaviorData;
        Formation::SP _formation;
        float _formationAngularSpeed;
        unsigned int _assignmentMode;

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

        SetFormationBehavior();
        virtual ~SetFormationBehavior();

        inline void setFormation(Formation::SP formation);
        inline void setAssignmentMode(Group::AssignmentMode::Value mode);
        inline void setFormationAngularSpeed(float speed);

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

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

        virtual void doAllocate(BehaviorGraph& graph) override;
        virtual void doDeallocate() override;
        virtual void doResize(BehaviorGraph& graph) override;
#ifndef NDEBUG
        virtual void doInit(BehaviorGraph& graph) override;
#endif
        virtual void doInit(int64_t index, BehaviorGraph& graph) override;
        virtual void doFinish(int64_t index, 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;
    };

    //-------------------------------------------------------------------------
    inline void SetFormationBehavior::setFormation(Formation::SP formation)
    {
        _formation = formation;

        size_t numUsers = _setFormationBehaviorData.size();
        for (size_t index = 0; index < numUsers; ++index)
        {
            _setFormationBehaviorData[index]._formationSet = false;
        }
    }

    //-------------------------------------------------------------------------
    inline void SetFormationBehavior::setAssignmentMode(Group::AssignmentMode::Value mode)
    {
        _assignmentMode = mode;
    }

    //-------------------------------------------------------------------------
    inline void SetFormationBehavior::setFormationAngularSpeed(float speed)
    {
        _formationAngularSpeed = speed;
        size_t numUsers = _setFormationBehaviorData.size();
        for (size_t index = 0; index < numUsers; ++index)
        {
            _setFormationBehaviorData[index]._formationSet = false;
        }
    }

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