#pragma once

#include "PtrData.h"

namespace ehs
{
	template<typename T>
	class ShdPtr
	{
	private:
		T* data;

	public:
		~ShdPtr()
		{
			if (RemovePtrData(data))
				delete data;
		}

		ShdPtr()
			: data(nullptr)
		{
		}

		ShdPtr(T* data)
			: data(data)
		{
			AddPtrData(data);
		}

		ShdPtr(ShdPtr&& shdPtr) noexcept
			: data(shdPtr.data)
		{
			shdPtr.data = nullptr;
		}

		ShdPtr(const ShdPtr& shdPtr)
			: data(shdPtr.data)
		{
			AddPtrData(data);
		}

		ShdPtr& operator=(ShdPtr&& shdPtr) noexcept
		{
			if (this == &shdPtr)
				return *this;

			if (RemovePtrData(data))
				delete data;

			data = shdPtr.data;

			shdPtr.data = nullptr;

			return *this;
		}

		ShdPtr& operator=(const ShdPtr& shdPtr) noexcept
		{
			if (this == &shdPtr)
				return *this;

			if (RemovePtrData(data))
				delete data;

			data = shdPtr.data;

			AddPtrData(data);

			return *this;
		}

		bool operator==(const ShdPtr& shdPtr)
		{
			if (!HasPtrData(data))
				data = nullptr;

			return data == shdPtr.data;
		}

		bool operator==(T* inPtr)
		{
			if (!HasPtrData(data))
				data = nullptr;

			return data == inPtr;
		}

		bool operator!=(const ShdPtr& shdPtr)
		{
			if (!HasPtrData(data))
				data = nullptr;

			return data != shdPtr.data;
		}

		bool operator!=(T* inPtr)
		{
			if (!HasPtrData(data))
				data = nullptr;

			return data != inPtr;
		}

		void Release()
		{
			if (RemovePtrData(data))
				delete data;

			data = nullptr;
		}

		T* GetData()
		{
			if (!HasPtrData(data))
				data = nullptr;

			return data;
		}
	};
}