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

#pragma once

#include "glmSDKAPI.h"
#include "glmTypes.h"
#include "glmMemory.h"
#include "glmAssert.h"

namespace glm
{
class GLM_SDK_API SimuEntityHandle
{
  public:
    GLM_CLASS_STAT_ID( glm::MemoryStatIds::Simulation);

    SimuEntityHandle();
    SimuEntityHandle(int typeIndex, int64_t index, bool isGroup = false);

    bool operator==(const SimuEntityHandle& other) const
    {
        GLM_COMPILE_TIME_ASSERT(sizeof(SimuEntityHandle) == sizeof(uint64_t));
        return *((uint64_t*)(this)) == *((uint64_t*)&other);
        //was getUint64() == other.getUint64();
    }

    bool operator!=(const SimuEntityHandle& other) const
    {
        return *((uint64_t*)(this)) != *((uint64_t*)&other);
        //was return getUint64() != other.getUint64();
    }

    // to be able to make map and set of SimuEntityHandle
    bool operator<(const SimuEntityHandle& other) const
    {
        return *((uint64_t*)(this)) < *((uint64_t*)&other);
    }

    // to be able to make map and set of SimuEntityHandle
    bool operator>(const SimuEntityHandle& other) const
    {
        return *((uint64_t*)(this)) > *((uint64_t*)&other);
    }

    inline void setUint64(uint64_t uintValue);
    inline uint64_t getUint64() const;

    inline void set(uint64_t index, uint64_t typeIndex, uint64_t isGroup);

    uint64_t _index : 43;
    uint64_t _isGroup : 1;
    uint64_t _typeIndex : 20;

    static SimuEntityHandle _invalidHandle;
};

//-------------------------------------------------------------------------
inline uint64_t SimuEntityHandle::getUint64() const
{
    return (uint64_t)_typeIndex << 44 | (uint64_t)_isGroup << 43 | (uint64_t)_index;
}

//-------------------------------------------------------------------------
inline void SimuEntityHandle::setUint64(uint64_t uintValue)
{
    _index = uintValue & 0x000007FFFFFFFFFF;
    _isGroup = (uintValue & 0x0000080000000000) >> 43;
    _typeIndex = (uintValue & 0xFFFFF00000000000) >> 44;
}

//-------------------------------------------------------------------------
inline void SimuEntityHandle::set(uint64_t typeIndex, uint64_t index, uint64_t isGroup)
{
    _index = index;
    _typeIndex = typeIndex;
    _isGroup = isGroup;
}
} // namespace glm
