#pragma once

#include "ehs/Types.h"
#include "ehs/Serializer.h"

namespace ehs
{
	class DbVarTmpl;
	class DbObject;

	class EHS_LIB_IO DbVar
	{
	private:
		friend class DbObject;

		UInt_64 hashId;
		DbObject *parent;
		Byte *value;
		UInt_64 size;

	public:
		~DbVar();

		DbVar();

		DbVar(UInt_64 hashId, const DbVarTmpl *master);

		DbVar(DbVar &&var) noexcept;

		DbVar(const DbVar &var);

		DbVar &operator=(DbVar &&var) noexcept;

		DbVar &operator=(const DbVar &var);

		explicit operator Byte *() const;

		UInt_64 GetHashId() const;

		template<typename T>
		void SetValueArray(const T* const newValue, const UInt_64 newSize)
		{
			size = sizeof(T) * newSize;

			value = new Byte[size];

			Util::Copy(value, newValue, size);
		}

		template<typename T = Char_8>
		void SetValueStr(const T * const newValue)
		{
			size = sizeof(T) * Str<Char_8, UInt_64>::Len(newValue);

			value = new Byte[size];

			Util::Copy(value, newValue, size);
		}

		template<typename T = Char_8, typename I = UInt_64>
		void SetValueStr(const Str<T, I>& newValue)
		{
			size = newValue.Size(true);

			value = new Byte[size];

			Util::Copy(value, &newValue[0], size);
		}

		template<typename T>
		void SetValue(const Byte* newValue)
		{
			size = sizeof(T);

			value = new Byte[size];

			Util::Copy(value, newValue, size);
		}

		template<typename T>
		T* GetValueArray() const
		{
			return (T*)value;
		}

		template<typename T = Char_8, typename I = UInt_64>
		Str<T, I> GetValueStr() const
		{
			return {(T*)value, size / sizeof(T)};
		}

		template<typename T>
		T GetValue() const
		{
			return *(T*)value;
		}

		UInt_64 GetSize() const;

	private:
		void Serialize(Serializer<UInt_64> &data) const;

		void Deserialize(Serializer<UInt_64> &data);
	};
}