#pragma once
#include "nodes.h"

namespace enginend::nodes::trid {
	struct node3d:public node {
		Vector3 pos,rot,size,scale;
		Camera3D* watcher;
		Shader* shader;
		Color tint;
		node3d(){}
		node3d(Vector3 pos,Vector3 rot,Vector3 size,Vector3 scale):
			pos(pos),rot(rot),scale(scale),size(size) {
			tint={255,255,255,255};
		}
	};

	struct physicsagent:virtual public node3d {
		bool hardbody,isphysics;
		std::vector<BoundingBox>* bboxes;
		physicsagent():hardbody(false),isphysics(false) {
			bboxes = new std::vector<BoundingBox>();
		}
		physicsagent(bool hardbody,bool isphysics):hardbody(hardbody),isphysics(isphysics) {
			bboxes = new std::vector<BoundingBox>();
		}
		physicsagent(bool hardbody,bool isphysics,std::vector<BoundingBox>* bboxes):
		hardbody(hardbody),isphysics(isphysics),bboxes(bboxes) {
			
		}
	};
	
	struct billboard:virtual public physicsagent {
		Texture2D* texture;
		billboard(){texture=nullptr;}
		billboard(Vector3 pos,Vector3 rot,Vector3 size,Vector3 scale,Texture2D* texture):
			node3d(pos,rot,size,scale),texture(texture){}
		void boot() override {
			
		}
		void draw() override {
			DrawBillboard(*watcher,*texture,pos,1.,tint);
		}
		void exit() override {
		}
	};
	struct object3d:public physicsagent {
		Model* model;
		void draw() override {
			DrawModel(*model,pos,1.,tint);
		}
		void exit() override {
		}
	};
	
	struct animatedbillboard:virtual public physicsagent {
		Image animimage;
		int frames;
		int currentframe;
		int framedelay;
		int framecounter;
		unsigned int nextframeoffset;
		int prevframe;
		Texture2D* texture;
		
		animatedbillboard() : frames(0), currentframe(0), framedelay(6), framecounter(0), nextframeoffset(0) {
			animimage.data = nullptr;
		}

		animatedbillboard(const char* gifpath, int delay = 6,Vector3 pos={},Vector3 rot={},Vector3 size={},Vector3 scale={}):node3d(pos,rot,size,scale),
			  framedelay(delay), currentframe(0), framecounter(0), frames(0), nextframeoffset(0)
		{
			animimage = LoadImageAnim(gifpath, &frames);
			if (frames > 0) {
				texture = new Texture2D(LoadTextureFromImage(animimage));
			}
		}
		void tick() override {
			if (frames <= 1) return;

			framecounter++;
			if (framecounter >= framedelay) {
				framecounter = 0;
				currentframe++;
				if (currentframe >= frames) currentframe = 0;
				nextframeoffset = animimage.width * animimage.height * 4 * currentframe;
			}
		}
		
		void draw() override {
		
			if (prevframe!=currentframe){
				prevframe=currentframe;
				UpdateTexture(*this->texture,((unsigned char*)animimage.data)+nextframeoffset);
			}
			DrawBillboard(*watcher,*texture,pos,1.,tint);
		}
		void exit() override {
			if (animimage.data) UnloadImage(animimage);
			if (texture) {
				UnloadTexture(*texture);
				delete texture;
				texture = nullptr;
			}
		}
	};
	struct animatedmodel:virtual public physicsagent {
		std::vector<ModelAnimation> *animation;
		Model *model;
		int animcount;
		int curranimation=0;
		int currentframe=0;
		animatedmodel() {
			model = nullptr;
			animation = nullptr;
		}
		animatedmodel(Model *model,std::vector<ModelAnimation>* animation,int animcount,Vector3 pos,Vector3 rot,Vector3 size,Vector3 scale):
			model(model), animation(animation),node3d(pos,rot,size,scale),animcount(animcount)
		{}
		void draw() override {
			UpdateModelAnimationBones(*model,(*animation)[curranimation],currentframe++);
			if (currentframe >= (*animation)[curranimation].frameCount) currentframe = 0;
			DrawModel(*model,pos,1.,tint);
		}
		void exit() override {
		}
	};
	
}