#pragma once

#include "ehs/EHS.h"
#include "ehs/Array.h"
#include "ehs/io/File.h"
#include "MdlCodec.h"
#include "Mesh.h"
#include "Bone.h"
#include "Animation.h"

namespace ehs
{
	enum class ModelEncoding : UInt_8
	{
		EHM
	};

	class EHS_LIB_IO Mdl : public BaseObj
	{
	private:
		static Array<MdlCodec> codecs;

	protected:
		UInt_64 hashId;
		Str_8 id;
		Array<Mesh> meshes;
		Bone skeleton;
		Array<Animation> animations;

	public:
		static bool HasCodec(UInt_64 hashExt);

		static bool HasCodec(const Str_8& ext);

		static bool AddCodec(MdlCodec codec);

		static const MdlCodec* GetCodec(UInt_64 hashExt);

		static const MdlCodec* GetCodec(const Str_8& ext);

		Mdl();

		Mdl(const Str_8& filePath);

		Mdl(Str_8 id, Array<Mesh> meshes, Bone skeleton, Array<Animation> animations);

		Mdl(Str_8 id, Array<Mesh> meshes, Bone skeleton);

		Mdl(Str_8 id, Array<Mesh> meshes);

		Mdl(Mdl&& model) noexcept;

		Mdl(const Mdl& model) = default;

		Mdl& operator=(Mdl&& model) noexcept;

		Mdl& operator=(const Mdl& model) = default;

		void Release();

		UInt_64 GetHashId() const;

		void SetId(Str_8 newId);

		Str_8 GetId() const;

		const Array<Mesh>& GetMeshes() const;

		Array<Mesh>& GetMeshes();

		Mesh* GetMesh(UInt_64 inHashId);

		Mesh* GetMesh(const Str_8& inId);

		const Bone& GetSkeleton() const;

		Bone& GetSkeleton();

		Animation* GetAnimation(UInt_64 inHashId);

		const Array<Animation>& GetAnimations() const;

		Array<Animation>& GetAnimations();

		void Calculate();

		bool Export(const Str_8& filePath) const;
	};

	bool EncodeEHM(const MdlCodec* codec, Serializer<UInt_64>& data, const Mdl* mdl);

	bool DecodeEHM(const MdlCodec* codec, Serializer<UInt_64>& data, Mdl* mdl);
}