
#ifndef PORYGONLANG_USERDATASTORAGE_HPP
#define PORYGONLANG_USERDATASTORAGE_HPP

#include <unordered_map>
#include "UserData.hpp"
#include <mutex>

namespace Porygon::UserData {
    class UserDataStorage {
    private:
        class _internalDataStorage {
        public:
            std::unordered_map<uint32_t, std::unique_ptr<UserData>> _userData;

            _internalDataStorage()
            : _userData(std::unordered_map<uint32_t, std::unique_ptr<UserData>>(0))
            {
            }

            ~_internalDataStorage(){
                _userData.clear();
            }

            _internalDataStorage( const UserDataStorage& ) = delete; // non construction-copyable
            _internalDataStorage& operator=( const UserDataStorage& ) = delete; // non copyable

        };

        static _internalDataStorage _internal;
        static std::mutex _userDataMutex;
    public:
        static void RegisterType(uint32_t i, UserData *ud) {
            std::lock_guard<std::mutex> guard(_userDataMutex);
            UserDataStorage::_internal._userData.insert({i, std::unique_ptr<UserData>(ud)});
        }

        static void RemoveType(uint32_t key){
            _internal._userData.erase(key);
        }

        inline static bool HasUserDataType(uint32_t i) {
            return UserDataStorage::_internal._userData.find(i) != UserDataStorage::_internal._userData.end();
        }

        inline static UserData* GetUserDataType(uint32_t i) {
            return UserDataStorage::_internal._userData.at(i).get();
        }
    };
}

#endif //PORYGONLANG_USERDATASTORAGE_HPP
