﻿#pragma once
#include "render/Renderer.h"
#include <unordered_map>


namespace ZL
{
	constexpr int MAX_BONE_COUNT = 6;
	constexpr int MAX_GPU_BONES = 64;
	struct Bone
	{
		Vector3f boneStartWorld;
		float boneLength;
		Matrix4f boneMatrixWorld;
		// boneVector = boneLength * (0, 1, 0) � ���� ��������
		// Then multiply by boneMatrixWorld � �� �������� �������� �����

		int parent;
		std::vector<int> children;
	};

	struct BoneWeight
	{
		int boneIndex = -1;
		float weight = 0;
	};

	struct AnimationKeyFrame
	{
		int frame;
		std::vector<Bone> bones;
	};

	struct Animation
	{
		std::vector<AnimationKeyFrame> keyFrames;
	};

	struct GpuBoneData {
		std::vector<Vector4f> boneIndices0;  // bone indices 0-3 per vertex (as float)
		std::vector<Vector2f> boneIndices1;  // bone indices 4-5 per vertex
		std::vector<Vector4f> boneWeights0;  // bone weights 0-3 per vertex
		std::vector<Vector2f> boneWeights1;  // bone weights 4-5 per vertex
		bool prepared = false;
	};

	struct BoneSystem
	{
		VertexDataStruct mesh;
		VertexDataStruct startMesh;
		std::vector<std::array<BoneWeight, MAX_BONE_COUNT>> verticesBoneWeight;

		Matrix4f armatureMatrix;

		std::vector<Bone> startBones;
		std::vector<Bone> currentBones;

		std::vector<Animation> animations;
		int startingFrame = 0;

		GpuBoneData gpuBoneData;

		void LoadFromFile(const std::string& fileName, const std::string& ZIPFileName = "");
		void LoadFromBinaryFile(const std::string& fileName, const std::string& ZIPFileName = "");

		void Interpolate(int frame);

		// GPU skinning: prepare per-vertex bone data for VBO upload
		void PrepareGpuSkinningData();
		// GPU skinning: compute skinning matrices without modifying the mesh
		void ComputeSkinningMatrices(int frame, std::vector<Matrix4f>& outMatrices) const;
	};




};