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

#pragma once

#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>

#include "glmRTTI.h"
#include "glmAttribute.h"
#include "glmAccessorsAttribute.h"
#include "glmDeque.h"
#include "glmList.h"
#include "glmMap.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include "glmString.h"
#include <float.h>
#include <assert.h>
#include <limits>

#include <glmSDKAPI.h>

#include <glmArray.h>
#include <glmLog.h>
#include <glmCoreDefinitions.h>

//===============================================================================
#if GLM_IS_COMPILER_MSVC
#include <direct.h>

//#define WINVER 0x0501
#endif
//===============================================================================

#define CSV_LOG_ALL 0
#define CSV_LOG_MAX_ENTITY_INDEX 50

namespace glm
{
    //************************************************************
    //! @name Structures and types
    //************************************************************
    //@{

    //-------------------------------------------------------------------------
    // AnimationReplayMode
    //-------------------------------------------------------------------------
    struct GLM_SDK_API AnimationReplayMode
    {
    public:
        enum Value
        {
            ABSOLUTE_MODE = 0,
            REST_RELATIVE,
            //POSITION_DELAY,	not available yet
            //MASS_SPRING_DAMPER,	not available yet
            END
        };
    };

    //-------------------------------------------------------------------------
    // ChannelInfo
    //-------------------------------------------------------------------------
    struct GLM_SDK_API ChannelInfo
    {
        GLM_RTTI("f22c9cb8-bf66-46c3-8a8c-7192351a7b19", glm::ChannelInfo, addAttributes)

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

        ChannelInfo();
        ChannelInfo(const ChannelInfo& source);
        ChannelInfo& operator=(const ChannelInfo& source);
        ~ChannelInfo();

        //NOTE: 1st bone index is the limb auxiliary, 2nd is the limb extension, then 2 bones per effector (auxiliary+extension)
        const int getNbEffectors() const
        {
            return static_cast<const int>((_genericBoneIndices.size() > 2) ? (_genericBoneIndices.size() - 2) / 2 : 0);
        }

        glm::PODArray<int> _genericBoneIndices;
        int _fatherSpineGenericBoneIndex; // -1 means none

    private:
        static void addAttributes();
    };

    //-------------------------------------------------------------------------
    // ChannelReplayParameters
    //-------------------------------------------------------------------------
    struct GLM_SDK_API ChannelReplayParameters
    {
        GLM_RTTI("bc586e5e-25af-4bfc-a34c-7425bf04deca", glm::ChannelReplayParameters, addAttributes)

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

        ChannelReplayParameters()
            : _limbAuxiliaryReplayMode(AnimationReplayMode::REST_RELATIVE)
            , _limbAuxiliaryAdditionalIkNormalOffset(0)
            , _limbExtensionReplayMode(AnimationReplayMode::ABSOLUTE_MODE)
            , _limbExtensionAdditionalIkNormalOffset(0)
            , _effectorAuxiliaryReplayMode(AnimationReplayMode::REST_RELATIVE)
            , _effectorExtensionReplayMode(AnimationReplayMode::ABSOLUTE_MODE)
        {
        }

        AnimationReplayMode::Value _limbAuxiliaryReplayMode;
        Angle _limbAuxiliaryAdditionalIkNormalOffset;
        AnimationReplayMode::Value _limbExtensionReplayMode;
        Angle _limbExtensionAdditionalIkNormalOffset;

        AnimationReplayMode::Value _effectorAuxiliaryReplayMode;
        AnimationReplayMode::Value _effectorExtensionReplayMode;

    private:
        static void addAttributes();

        void setLimbAuxiliaryReplayMode(int replayMode)
        {
            _limbAuxiliaryReplayMode = (AnimationReplayMode::Value)replayMode;
        }
        int getLimbAuxiliaryReplayMode() const
        {
            return (int)_limbAuxiliaryReplayMode;
        }
        void setLimbExtensionReplayMode(int replayMode)
        {
            _limbExtensionReplayMode = (AnimationReplayMode::Value)replayMode;
        }
        int getLimbExtensionReplayMode() const
        {
            return (int)_limbExtensionReplayMode;
        }

        void setEffectorAuxiliaryReplayMode(int replayMode)
        {
            _effectorAuxiliaryReplayMode = (AnimationReplayMode::Value)replayMode;
        }
        int getEffectorAuxiliaryReplayMode() const
        {
            return (int)_effectorAuxiliaryReplayMode;
        }
        void setEffectorExtensionReplayMode(int replayMode)
        {
            _effectorExtensionReplayMode = (AnimationReplayMode::Value)replayMode;
        }
        int getEffectorExtensionReplayMode() const
        {
            return (int)_effectorExtensionReplayMode;
        }
    };

    struct GLM_SDK_API RagdollRigidBodyIndex
    {
        enum Value
        {
            BODYPART_PELVIS = 0,
            BODYPART_SPINE,
            BODYPART_BUST,
            BODYPART_HEAD,

            BODYPART_LEFT_UPPER_LEG,
            BODYPART_LEFT_LOWER_LEG,

            BODYPART_RIGHT_UPPER_LEG,
            BODYPART_RIGHT_LOWER_LEG,

            BODYPART_LEFT_UPPER_ARM,
            BODYPART_LEFT_LOWER_ARM,
            BODYPART_LEFT_HAND,

            BODYPART_RIGHT_UPPER_ARM,
            BODYPART_RIGHT_LOWER_ARM,
            BODYPART_RIGHT_HAND,

            END
        };
    };

    struct GLM_SDK_API LoadMotionErrorCode
    {
        enum Value
        {
            SUCCESS,
            FILE_NOT_FOUND,
            INCORRECT_VERSION,
            INVALID_FILE,
            END
        };
    };

    struct GLM_SDK_API SaveMotionErrorCode
    {
        enum Value
        {
            SUCCESS,
            FILE_CREATION_FAILED,
            END
        };
    };

    struct GLM_SDK_API LoadMotionMappingErrorCode
    {
        enum Value
        {
            SUCCESS,
            FILE_NOT_FOUND,
            INCORRECT_VERSION,
            END
        };
    };

    struct GLM_SDK_API SaveMotionMappingErrorCode
    {
        enum Value
        {
            SUCCESS,
            FILE_CREATION_FAILED,
            END
        };
    };

    struct GLM_SDK_API EditMotionParameters
    {
        double _deltaTime;
        Vector3 _deltaNormalizedPosition;
        float _deltaHeading;
        bool _applyPosOriDeltaOnBlendingFramesOnly;
        bool _fixLoopingOffset;
        Vector3 _movingDirection;
        int _firstBlendingFrame;
        int _lastBlendingFrame;
        int _correctFromBeginOrEnd;
    };
    //@}
} // namespace glm
