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

#pragma once

#include "glmSDKAPI.h"

//golaem core includes
#include <glmAbstractUserBehavior.h>
#include <glmTrafficContext.h>
#include <glmTrafficVehicle.h>

namespace glm
{
    // Traffic behavior, provides a traffic pipeline to an entity.
    class GLM_SDK_API TrafficBehavior : public AbstractUserBehavior
    {
    public:
        class GLM_SDK_API TrafficBehaviorData
        {
        public:
            float _maxAcceleration;
            float _maxDeceleration;
            float _maxSpeed;
            float _maxSpeedWhenTurning;
            float _maxAngularSpeed;
            float _respectRatio;
            float _safetyDistance;
            float _lateralNoise;
            Vehicle::LateralNoiseScope::Value _lateralNoiseScope;

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

            TrafficBehaviorData();
            ~TrafficBehaviorData();
        };

        float _width;
        float _length;

    private:
        TrafficContext* _trafficContext;

        //// config - needed to be able to revert trains
        //int					_vehicleTrailerSpecificBoneId;	// to get its physicsShape for size
        //glm::PODArray<int>	_vehicleTowSpecificBoneIds;		// to get their physicsShape for size

        glm::Array<TrafficBehaviorData> _trafficBehaviorData;

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

        void setSpeeds(int64_t index,
                       float maxSpeed,
                       float speedWhenTurning,
                       float maxAcceleration,
                       float maxDeceleration,
                       float maxAngularSpeed,
                       float respectRatio,
                       float safetyDistance,
                       float lateralNoise,
                       Vehicle::LateralNoiseScope::Value lateralNoiseScope);

        TrafficBehavior();
        virtual ~TrafficBehavior();

        //void setTrailerBone(int trailerBoneId);
        //void addTowBone(int towBoneId);

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

    protected:
        // cloning
        friend class CloneFactory;
        inline virtual TrafficBehavior* 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 doFinish(BehaviorGraph& graph) override;
        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;

    private:
        void setVehicleProperties(int64_t index, BehaviorGraph& graph, TrafficEntityComponent& trafficComponent);

        //void clearTrafficData(int64_t index, BehaviorGraph& graph);
    };

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