#include "../Base.h"
#include "Animation.h"
#include <vector>
#include "Pointer.h"
#include "FontTheme.h"

namespace gorgon {

	void LoadAnimationEx(Animation &anim, Base *parent, File &file, std::istream &in, int Size, std::function<bool(std::istream&, GID::Type, int)> loadextra) {
		if(parent)
			anim.SetParent(*parent);
		else
			anim.RemoveParent();


		std::vector<namecaption> names;

		LoadEntries(in, Size, file, anim, [&](GID::Type &gid, int size) -> bool {
			switch(gid) {
			case gge::resource::GID::Animation_Image:
				gid=gge::resource::GID::Image;
				return false;

			case gge::resource::GID::Animation_Names:
				LoadNames(in, size, names, gge::resource::GID::Animation_Name);
				return true;

			case gge::resource::GID::Animation_Durations:
				unsigned t;
				t=0;

				for(int i=0;i<size/4;i++) {
					unsigned d=gge::resource::ReadFrom<int>(in);
					anim.Frames.push_back(gge::resource::AnimationFrame(d,t));

					t+=d;
				}

				anim.TotalLength=t;

				return true;
			default:
				if(loadextra)
					return loadextra(in, gid, size);
				else
					return false;
			}
		}, names);

		unsigned i=0;
		for(auto it=anim.gorgon::Base::Subitems.First();it.IsValid();it.Next(), i++) {
			if(i<anim.Frames.size()) {
				anim.Frames[i].Image=&dynamic_cast<Image&>(*it);
			}
			else {
				anim.Frames.push_back(gge::resource::AnimationFrame(42, anim.TotalLength, &dynamic_cast<Image&>(*it)));
				anim.TotalLength=42;
			}
		}

		anim.FrameCount=anim.Frames.size();


	}

	Animation *LoadAnimation(Base *parent, File &file, std::istream &in, int Size) {
		Animation &anim=*new Animation;
		LoadAnimationEx(anim, parent, file, in, Size);
		return &anim;
	}

	Pointer *LoadPointer(Base *parent, File &File, std::istream &Data, int Size) {
		Pointer &pointer=*new Pointer;
		if(parent)
			pointer.SetParent(*parent);
		else
			pointer.RemoveParent();

		LoadAnimationEx(pointer.GetAnimation(), parent, File, Data, Size, [&](std::istream &in, GID::Type gid, int size) -> bool {
			if(gid==gge::resource::GID::Pointer_Props) {
				gge::resource::ReadFrom(Data, pointer.Hotspot);
				pointer.Type=(gge::Pointer::PointerType)gge::resource::ReadFrom<int>(Data);

				return true;
			}

			return false;
		});

		return &pointer;
	}

	FontTheme *LoadFontTheme(gorgon::Base *parent, File &file, std::istream &in, int Size) {
		FontTheme &ft=*new FontTheme;
		if(parent)
			ft.SetParent(*parent);
		else
			ft.RemoveParent();

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, ft, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::resource::GID::FontTheme_Props) {
				ft.guid_normal	.Load(in);
				ft.guid_bold	.Load(in);
				ft.guid_italic	.Load(in);
				ft.guid_small	.Load(in);
				ft.guid_h1		.Load(in);
				ft.guid_h2		.Load(in);
				ft.guid_h3		.Load(in);

				return true;
			}

			return false;
		}, names);

		return &ft;
	}

}
