#include "BitmapFont.h"
#include "../Generic/Image.h"
#include <Engine/OS.h>


namespace gorgon {


	void BitmapFont::ImportDirectory(const std::string &directory, bool trim, int zero) {
		gge::os::filesystem::DirectoryIterator it(directory, "*.png");

		Image *img=NULL;

		for(;it.IsValid();it.Next()) {
			std::string charid=it->substr(0,it->length()-4);
			std::stringstream ss(charid);
			int ind=-1;
			ss>>ind;
			if(ind!=-1) {
				img=new Image;
				if(img->ImportPNG(directory+"/"+*it)==img->NoError) {
					if(trim) {
						Image *old=img;
						img=new Image;

						gge::graphics::RGBint *olddata=(gge::graphics::RGBint *)old->GetData();

						int ow=old->GetWidth();
						int oh=old->GetHeight();

						int start=0, end=ow;

						for(int x=0;x<ow;x++) {
							bool found=false;
							for(int y=0;y<oh;y++) {
								if(olddata[x+y*ow].a) {
									found=true;
									break;
								}
							}

							if(found) {
								start=x;
								break;
							}
						}

						for(int x=ow-1;x>=0;x--) {
							bool found=false;
							for(int y=0;y<oh;y++) {
								if(olddata[x+y*ow].a) {
									found=true;
									break;
								}
							}

							if(found) {
								end=x+1;
								break;
							}
						}

						int nw=end-start;
						img->Resize(nw, oh, old->GetMode());
						gge::graphics::RGBint *newdata=(gge::graphics::RGBint *)img->GetData();

						for(int x=start;x<end;x++) {
							for(int y=0;y<oh;y++) {
								newdata[x-start+y*nw]=olddata[x+y*ow];
							}
						}
					}
					Add((char)(ind+zero), *img);
					Baseline=(int)(img->GetHeight()*0.7);
					VerticalSpacing=(int)(img->GetHeight()+1);
				}
				else
					delete img;
			}
		}

		for(int i=0;i<256;i++) {
			if(!Characters[i]) {
				Characters[i]=img;
			}
		}

		if(trim) {
			Seperator=1;
		}
	}

	void BitmapFont::Save(std::ostream &out) {
		auto start=WriteObjectStart(out, *this);


		auto mapstart=WriteSectionStart(out, gge::resource::GID::Font_Charmap);
		
		int chmap[256];
		
		for(int i=0;i<256;i++) {
			chmap[i]=gorgon::Base::Subitems.FindLocation(dynamic_cast<gorgon::Base*>(Characters[i]));
		}
		
		out.write((char*)chmap, 256*4);
		
		WriteEnd(out, mapstart);


		auto propstart=WriteSectionStart(out, gge::resource::GID::Font_Props);

		WriteTo(out, Seperator);
		WriteTo(out, VerticalSpacing);
		WriteTo(out, Baseline);

		WriteEnd(out, propstart);


		WriteNames(out, *this, gge::resource::GID::Font_Names, gge::resource::GID::Font_Name);

		WriteSubItems(out, *this);


		WriteEnd(out, start);
	}

	BitmapFont *LoadBitmapFont(Base *parent, File &file, std::istream &in, int Size) {
		BitmapFont &fnt=*new BitmapFont;
		if(parent)
			fnt.SetParent(*parent);
		else
			fnt.RemoveParent();

		int chmap[256]={};
		unsigned cpos=0;


		std::vector<namecaption> names;

		LoadEntries(in, Size, file, fnt, [&](GID::Type &gid, int size) -> bool {
			switch(gid) {
			case gge::resource::GID::Font_Image:
			case gge::resource::GID::Image: {
				Image *img=LoadImage(parent, file, in, size);

				for(unsigned i=0;i<256;i++)
					if((unsigned)chmap[i]==cpos)
						fnt.Characters[i]=img;

				if(cpos<names.size()) {
					img->SetCaption(names[cpos].caption);
					img->SetName(names[cpos].name);
				}

				fnt.gorgon::Base::Subitems.Add(img);

				cpos++;
				return true;
			}

			case gge::resource::GID::Font_Names:
				LoadNames(in, size, names, gge::resource::GID::Font_Name);
				return true;

			case gge::resource::GID::Font_Charmap:
				in.read((char*)chmap, 256*4);

				return true;

			case gge::resource::GID::Font_Props:
				gge::resource::ReadFrom(in,fnt.Seperator);
				gge::resource::ReadFrom(in,fnt.VerticalSpacing);
				gge::resource::ReadFrom(in,fnt.Baseline);

				return true;
			default:
				return false;
			}
		}, names);

		return &fnt;
	}



}