#pragma once

#include <vector>
#include <string>
#include <Widgets/Main.h>
#include <Widgets/FullscreenPanel.h>
#include <Widgets/Tabpanel.h>
#include <Widgets/Listbox.h>
#include "../Common/FileHandling.h"
#include "../Common/ImageImport.h"
#include "../Common/ImageList.h"
#include "CharacterList.h"
#include "DirectionSelector.h"
#include "AnimationEditor.h"
#include <iosfwd>
#include <Widgets/Dialogs/TextInput.h>
#include <Gorgon/Folder.h>
#include <Gorgon/Base.h>
#include <Gorgon/Game/Animation.h>
#include <Gorgon/Generic/DataArray.h>
#include <Widgets/Dialogs/Query.h>
#include <Widgets/Numberbox.h>
#include <Gorgon/Extended/Sound.h>
#include <Gorgon/Link.h>

static const int animnameoffset=5;

class UI {
public:

	UI() : changed(false), CurrentChar(NULL),
	CurrentAnim(NULL), CurrentDir(NULL)
	{
		CurrentFile.AddGameLoaders();
		CurrentFile.SetFileType(gorgon::GID::File::Game);

		os::window::Closing.RegisterLambda([&](bool &reply){
			if(changed) {
				AskQuit();
				reply=false;
			}
		});

		toplevel.Padding=0;

		navigation.Add("Files");
		navigation.Add("Char");
		navigation.SetContainer(toplevel);
		navigation.FillContainer();
		navigation.SetWidth(200);

		file.SetPanel(navigation("Files"));
		file.Quit.ClickEvent.RegisterLambda([&]{
			if(changed) AskQuit();
			else        Main.Exit(0);
		});
		file.New.ClickEvent.Register(this, &UI::NewFile);
		file.Load.ClickEvent.Register(this, &UI::LoadFile);
		file.Save.ClickEvent.RegisterLambda([&]{ actionafter=action_none; Save(); });
		file.SaveAs.ClickEvent.RegisterLambda([&]{ actionafter=action_none; AskSavename(); });
		file.RefreshFiles();

		chlist.SetPanel(navigation("Char"));
		chlist.Characters.ItemClickedEvent.Register(this, &UI::chlist_change);
		chlist.NewChar.ClickEvent.Register(this, &UI::NewChar);
		chlist.RenameChar.ClickEvent.Register(this, &UI::AskCharNewName);
		chlist.DeleteChar.ClickEvent.Register(this, &UI::AskDeleteChar);
		chlist.NewAnim.ClickEvent.Register(this, &UI::NewAnim);
		chlist.RenameAnim.ClickEvent.Register(this, &UI::AskAnimNewName);
		chlist.DeleteAnim.ClickEvent.Register(this, &UI::AskDeleteAnim);
		chlist.attach.ChangeEvent.RegisterLambda([&]{
			if(CurrentChar)
				CurrentChar->Get<gorgon::DataArray>(0).Get<resource::PointData>(1).value=chlist.attach.Value;
		});
		chlist.Type.ChangeEvent.RegisterLambda([&]{
			if(CurrentChar)
				CurrentChar->Get<gorgon::DataArray>(0).Get<resource::IntegerData>(2).value=chlist.Type.GetValue();
		});
		chlist.BaseColor.ChangeEvent.RegisterLambda([&]{
			if(CurrentChar)
				CurrentChar->Get<gorgon::DataArray>(0).Get<resource::ColorData>(3)=chlist.BaseColor.Value;
		});
		chlist.SecondColor.ChangeEvent.RegisterLambda([&]{
			if(CurrentChar)
				CurrentChar->Get<gorgon::DataArray>(0).Get<resource::ColorData>(4)=chlist.SecondColor.Value;
		});

		navigation("Char").Disable();
		navigation.reorganize();

		charedit.SetContainer(toplevel);
		charedit.Move(200, 0);
		charedit.Resize(toplevel.GetUsableWidth()-200, toplevel.GetUsableHeight()-charedit.GetY()-1);
		charedit.Hide();

		direction.SetContainer(charedit);
		direction.Move(0, 0);
		chlist.Animations.ItemClickedEvent.Register(this, &UI::SelectAnim);
		direction.ChangedEvent.Register(this, &UI::DirectionSelect);

		animsoundl.SetContainer(charedit);
		animsoundl.Text="Sound:";
		animsoundl.Move(direction.GetWidth()+2, direction.GetY());
		animsound.SetContainer(charedit);
		animsound.Move(animsoundl.GetBounds().BottomLeft());
		animsound.SetWidth(charedit.GetWidth()-animsound.GetLeft()-10);
		animsound.ChangeEvent.RegisterLambda([&]{
			if(CurrentAnim) {
				gorgon::Sound *snd=CurrentFile.Root().Get<gorgon::Folder>(1).GetPtr<gorgon::Sound>(animsound.GetValue());
				if(snd)
					CurrentAnim->Get<gorgon::Link>(4).SetTarget(*snd);
				else
					CurrentAnim->Get<gorgon::Link>(4).RemoveTarget();
			}
		});

		ImageBank.SetContainer(charedit);
		ImageBank.Move(0, direction.GetY()+direction.GetHeight());
		ImageBank.Resize(190, charedit.GetUsableHeight()-ImageBank.GetY()-1);
		ImageBank.SelectionType=ImageBank.MultiSelect;
		ImageBank.AllowReorder=true;

		animedit.SetContainer(charedit);
		animedit.Resize(190, charedit.GetUsableHeight()-animdur.GetHeight()-1-ImageBank.GetY()-1);
		animedit.Move(charedit.GetUsableWidth()-animedit.GetWidth()-1,direction.GetY()+direction.GetHeight());
		animedit.SelectionType=animedit.MultiSelect;
		animedit.ItemClickedEvent.RegisterLambda([&]{
			if(animedit.GetItem())
				animdur.Value=animedit.GetAnimation()->GetFrames()[animedit.FindLocation(animedit.GetItem())].Duration;
		});

		animdurl.SetContainer(charedit);
		animdurl.Text="Duration: ";
		animdurl.Move(animedit.GetX()+4, animedit.GetY()+animedit.GetHeight()+1);
		animdur.SetContainer(charedit);
		animdur.Move(animdurl.GetX()+animdurl.GetWidth()+1, animedit.GetY()+animedit.GetHeight()+1);
		animdur.Value=250;
		animdur.ChangeEvent.RegisterLambda([&]{
			animedit.duration=animdur.Value;
			for(auto it=animedit.GetSelectedItems().First();it.IsValid();it.Next()) {
				animedit.GetAnimation()->SetDuration(animedit.FindLocation(*it), animdur.Value);
			}
		});

		ImgAdd.Text=">>";
		ImgAdd.SetContainer(charedit);
		ImgAdd.Move(ImageBank.GetX()+ImageBank.GetWidth(), ImageBank.GetY()+2);
		ImgAdd.SetWidth(80);
		ImgAdd.ClickEvent.Register(this, &UI::AddFrame);

		ImgDup.Text="dup";
		ImgDup.SetContainer(charedit);
		ImgDup.Move(ImageBank.GetX()+ImageBank.GetWidth(), ImgAdd.GetY()+ImgAdd.GetHeight());
		ImgDup.SetWidth(80);
		ImgDup.ClickEvent.Register(this, &UI::DupFrame);

		ImgRemove.Text="<<";
		ImgRemove.SetContainer(charedit);
		ImgRemove.Move(ImageBank.GetX()+ImageBank.GetWidth(), ImgDup.GetY()+ImgDup.GetHeight());
		ImgRemove.SetWidth(80);
		ImgRemove.ClickEvent.Register(this, &UI::RemoveFrame);

		ImgAdd1.Text="1 >>";
		ImgAdd1.SetContainer(charedit);
		ImgAdd1.Move(ImageBank.GetX()+ImageBank.GetWidth(), ImgRemove.GetY()+ImgRemove.GetHeight()+8);
		ImgAdd1.SetWidth(80);
		ImgAdd1.ClickEvent.RegisterLambda([&]{AddFrames(1); });

		ImgAdd3.Text="3 >>";
		ImgAdd3.SetContainer(charedit);
		ImgAdd3.Move(ImageBank.GetX()+ImageBank.GetWidth(), ImgAdd1.GetY()+ImgAdd1.GetHeight());
		ImgAdd3.SetWidth(80);
		ImgAdd3.ClickEvent.RegisterLambda([&]{AddFrames(3); });

		ImgAdd3s.Text="dup 1, 2 >>";
		ImgAdd3s.SetContainer(charedit);
		ImgAdd3s.Move(ImageBank.GetX()+ImageBank.GetWidth(), ImgAdd3.GetY()+ImgAdd3.GetHeight());
		ImgAdd3s.SetWidth(80);
		ImgAdd3s.ClickEvent.RegisterLambda([&]{DupFrames(1); AddFrames(2); });

		ImgAdd4.Text="4 >>";
		ImgAdd4.SetContainer(charedit);
		ImgAdd4.Move(ImageBank.GetX()+ImageBank.GetWidth(), ImgAdd3s.GetY()+ImgAdd3s.GetHeight());
		ImgAdd4.SetWidth(80);
		ImgAdd4.ClickEvent.RegisterLambda([&]{AddFrames(4); });

		ImgAdd6.Text="6 >>";
		ImgAdd6.SetContainer(charedit);
		ImgAdd6.Move(ImageBank.GetX()+ImageBank.GetWidth(), ImgAdd4.GetY()+ImgAdd4.GetHeight());
		ImgAdd6.SetWidth(80);
		ImgAdd6.ClickEvent.RegisterLambda([&]{AddFrames(6);});

		ImgAdd7.Text="del 1, 6 >>";
		ImgAdd7.SetContainer(charedit);
		ImgAdd7.Move(ImageBank.GetX()+ImageBank.GetWidth(), ImgAdd6.GetY()+ImgAdd6.GetHeight());
		ImgAdd7.SetWidth(80);
		ImgAdd7.ClickEvent.RegisterLambda([&]{DeleteFrames(1); AddFrames(6);});

		ImgAdd8.Text="8 >>";
		ImgAdd8.SetContainer(charedit);
		ImgAdd8.Move(ImageBank.GetX()+ImageBank.GetWidth(), ImgAdd7.GetY()+ImgAdd7.GetHeight());
		ImgAdd8.SetWidth(80);
		ImgAdd8.ClickEvent.RegisterLambda([&]{AddFrames(8);});

		ImgAdd9.Text="del 1, 8 >>";
		ImgAdd9.SetContainer(charedit);
		ImgAdd9.Move(ImageBank.GetX()+ImageBank.GetWidth(), ImgAdd8.GetY()+ImgAdd8.GetHeight());
		ImgAdd9.SetWidth(80);
		ImgAdd9.ClickEvent.RegisterLambda([&]{DeleteFrames(1); AddFrames(8);});

		ImgDelete.Text=">> del";
		ImgDelete.SetContainer(charedit);
		ImgDelete.Move(ImageBank.GetX()+ImageBank.GetWidth(), ImgAdd9.GetY()+ImgAdd9.GetHeight()+8);
		ImgDelete.SetWidth(80);
		ImgDelete.ClickEvent.Register(this, &UI::DeleteSelectedFrames);

		ImgClear.Text="all >> del";
		ImgClear.SetContainer(charedit);
		ImgClear.Move(ImageBank.GetX()+ImageBank.GetWidth(), ImgDelete.GetY()+ImgDelete.GetHeight()+8);
		ImgClear.SetWidth(80);
		ImgClear.ClickEvent.Register(this, &UI::ClearAllFrames);

		imgimport.Ok.ClickEvent.Register(this, &UI::image_import);
	}

	void chlist_change()  {
		CurrentChar=&CurrentFile.Root().Get<gorgon::Folder>(chlist.Characters.GetValue());
		SelectChar();
	}

	void NewChar() {
		std::stringstream ss;
		ss<<"Char "<<CurrentFile.Root().GetCount()-1;
		widgets::dialog::AskText("Enter the name for the new character.", ss.str(), 
			"New Character").RepliedEvent.Register(this, &UI::CreateNewChar);
	}

	void NewAnim() {
		std::stringstream ss;
		ss<<"Anim "<<CurrentChar->GetCount();
		widgets::dialog::AskText("Enter the name for the new animation.", ss.str(), 
			"New Animation").RepliedEvent.Register(this, &UI::CreateNewAnim);
	}

	void CreateNewChar(const std::string &name) {
		gorgon::Folder &f=*new gorgon::Folder(name);
		gorgon::DataArray &d=*new gorgon::DataArray;
		
		d.SetCaption("Info");
		d.Add(name).name="ID";
		d.Add(chlist.attach.Value).name="Attach";
		d.Add((int)chlist.Type.GetValue()).name="Type";
		d.Add(chlist.BaseColor.Value).name="Base color";
		d.Add(chlist.SecondColor.Value).name="Second color";
		f.SetName(name);
		f.Add(d);

		CurrentFile.Root().Add(f);
		changed=true;

		chlist.Characters.Add(name).Accessed();

		CreateNewAnim("Stand");
		CreateNewAnim("Walk");
	}

	void CreateNewAnim(const std::string &name) {
		gorgon::Folder &f=*new gorgon::Folder(name);
		f.SetName(name);

		static const char *directionnames[]={"North", "West", "South", "East"};

		for(int i=0;i<4;i++) {
			gorgon::Animation &a=*new gorgon::Animation;
			a.SetCaption(directionnames[i]);
			a.SetName(directionnames[i]);
			f.Add(a);
		}

		gorgon::Link &sound=*new gorgon::Link;
		sound.SetCaption("Sound");
		f.Add(sound);
		
		std::stringstream ss;
		ss<<"Animation "<<CurrentChar->GetCount();

		CurrentChar->Get<gorgon::DataArray>(0).Add(name).name=ss.str();
		CurrentChar->Add(f);
		changed=true;

		chlist.Animations.Add(name).Accessed();
	}

	void AskDeleteChar() {
		auto &d=widgets::dialog::AskConfirm("This will delete the char permanently!", "Delete");
		d.RepliedEvent.RegisterLambda([&](bool reply) { if(reply) DeleteChar(); });
	}

	void DeleteChar() {
		if(CurrentChar)
			CurrentFile.Root().Delete(CurrentChar);

		ListChars();
		changed=true;
	}

	void AskDeleteAnim() {
		auto &d=widgets::dialog::AskConfirm("This will delete the animation permanently! No images will be returned back to pool.", "Delete");
		d.RepliedEvent.RegisterLambda([&](bool reply) { if(reply) DeleteAnim(); });
	}

	void DeleteAnim() {
		if(CurrentAnim) {
			int ind=CurrentChar->Subitems.FindLocation(CurrentAnim);
			CurrentChar->Get<gorgon::DataArray>(0).Delete(ind+animnameoffset);
			CurrentChar->Delete(CurrentAnim);
		}

		SelectChar();
		changed=true;
	}

	void AskCharNewName() {
		if(!CurrentChar) return;

		auto &d=widgets::dialog::AskText("Please enter the new name for the char.", CurrentChar->GetName(), "Rename");
		d.RepliedEvent.Register(this, &UI::RenameChar);
	}

	void RenameChar(const std::string &name) {
		CurrentChar->SetName(name);
		CurrentChar->SetCaption(name);
		CurrentChar->Get<gorgon::DataArray>(0).Get<resource::StringData>(0).value=name;
		chlist.Characters.GetItem()->Value=name;
		changed=true;
	}

	void AskAnimNewName()  {
		if(!CurrentAnim) return;

		auto &d=widgets::dialog::AskText("Please enter the new name for the animation.", CurrentAnim->GetName(), "Rename");
		d.RepliedEvent.Register(this, &UI::RenameAnim);
	}

	void RenameAnim(const std::string &name) {
		CurrentAnim->SetName(name);
		CurrentAnim->SetCaption(name);
		CurrentChar->Get<gorgon::DataArray>(0).Get<resource::StringData>(CurrentChar->Subitems.FindLocation(CurrentAnim)+animnameoffset).value=name;
		chlist.Animations.GetItem()->Value=name;
		changed=true;
	}

	void DirectionSelect() {
		CurrentDir=&(CurrentAnim->Get<gorgon::Animation>(direction.GetDirection()));
		animedit.SetAnimation(CurrentDir);
	}
	
	void SelectChar() {
		charedit.Hide();
		chlist.attach.Value=CurrentChar->Get<gorgon::DataArray>(0).getPoint(1);
		chlist.Type.SetValue((CharType::Type)CurrentChar->Get<gorgon::DataArray>(0).getInt(2));
		chlist.BaseColor.Value=CurrentChar->Get<gorgon::DataArray>(0).Get<resource::ColorData>(3);
		chlist.SecondColor.Value=CurrentChar->Get<gorgon::DataArray>(0).Get<resource::ColorData>(4);

		ListAnims();
	}

	void SelectAnim() {
		CurrentAnim=&CurrentChar->Get<gorgon::Folder>(chlist.Animations.GetValue());
		utils::Collection<animation::RectangularGraphic2DAnimation> animations;
		for(int i=0;i<4;i++) {
			auto &ap=CurrentAnim->Get<gorgon::Animation>(i);
			resource::ImageAnimation &a=ap.CreateResizableObject(true);
			animations.Add(dynamic_cast<animation::RectangularGraphic2DAnimation&>(a));
		}
		direction.SetAnimations(animations);
		charedit.Show(); 
		DirectionSelect();
		if(CurrentAnim->Get<gorgon::Link>(4).HasTarget())
			animsound.SetValue(CurrentAnim->Get<gorgon::Link>(4).GetTarget().GetName());
		else
			animsound.SetValue("[None]");
	}

	void AskQuit() {
		auto &d=widgets::dialog::AskConfirm("You have changed the file, do you wish to save?", "Quit");
		d.RepliedEvent.RegisterLambda([&](bool reply){
			if(reply) {
				actionafter=action_quit;
				Save();
				return;
			}
			else {
				Main.Exit(0);
			}
		});
		d.ShowCancel=true;
	}

	void AskSavename() {
		widgets::dialog::AskText("Enter the name for the file.", CurrentFile.GetFilename(), 
			"Save").RepliedEvent.RegisterLambda([&](const std::string &str) {
				CurrentFile.SetFilename(file.directory.Text+"/"+str);
				Save();
		});
	}

	bool Save() {
		if(CurrentFile.GetFilename()=="") {
			AskSavename();
			return false;
		}

		try {
			CurrentFile.SaveFile(CurrentFile.GetFilename());
		}
		catch(std::exception ex) {
			widgets::dialog::ShowMessage(std::string(ex.what())+"\nCheck if file path is valid.", "Save error");
		}
		changed=false;

		if(actionafter==action_newfile) {
			NewFile();
		}
		else if(actionafter==action_loadfile) {
			LoadFile();
		}
		else if(actionafter==action_quit) {
			Main.Exit(0);
		}

		return true;
	}

	void AskNew() {
		auto &d=widgets::dialog::AskConfirm("You have changed the file, do you wish to save?", "New file");
		d.RepliedEvent.RegisterLambda([&](bool reply){
			if(reply) {
				actionafter=action_newfile;
				Save();
				return;
			}
			else {
				ForceNewFile();
			}
		});
		d.ShowCancel=true;
	}

	void NewFile() {
		if(changed) {
			AskNew();
		}
		else {
			ForceNewFile();
		}
	}

	void ForceNewFile() {
		charedit.Hide();
		utils::Collection<animation::RectangularGraphic2DAnimation> anims;
		direction.SetAnimations(anims);
		animedit.SetAnimation(NULL);
		CurrentFile.New();
		CurrentFile.Root().Add(*new gorgon::Folder("Info"));

		gorgon::DataArray &dinf=*new gorgon::DataArray;
		dinf.SetCaption("Info");
		dinf.Add("trinlibr:anims").name="ID";

		CurrentFile.Root().Get<gorgon::Folder>(0).Add(dinf);

		CurrentFile.Root().Add(*new gorgon::Folder("Assets"));
		navigation("Char").Enable();
		file.Save.Enable();
		file.SaveAs.Enable();
		navigation.reorganize();
		navigation.Activate(navigation("Char"));
		chlist.NewFile();
		UpdateSoundList();
	}

	void AskLoad() {
		auto &d=widgets::dialog::AskConfirm("You have changed the file, do you wish to save?", "Load file");
		d.RepliedEvent.RegisterLambda([&](bool reply){
			if(reply) {
				actionafter=action_loadfile;
				Save();
				return;
			}
			else {
				ForceLoadFile();
			}
		});
		d.ShowCancel=true;
	}

	void LoadFile() {
		if(changed) {
			AskLoad();
		}
		else
			ForceLoadFile();

	}

	void ForceLoadFile() {
		std::string filename=(std::string)file.directory.Text + "/" + file.lst.GetValue().Filename;

		chlist.NewFile();
		CurrentFile.LoadFile(filename);
		CurrentFile.Prepare();

		if(CurrentFile.Root().Get<gorgon::Folder>(0).GetCount()==0) {
			gorgon::DataArray &dinf=*new gorgon::DataArray;
			dinf.SetCaption("Info");
			dinf.Add("trinlibr:anims").name="ID";

			CurrentFile.Root().Get<gorgon::Folder>(0).Add(dinf);
		}

		ListChars();
		navigation("Char").Enable();
		file.Save.Enable();
		file.SaveAs.Enable();
		navigation.reorganize();
		navigation.Activate(navigation("Char"));

		UpdateSoundList();
	}

	void UpdateSoundList() {
		if(!CurrentFile.Root().GetCount()) return;

		animsound.DeleteAll();
		animsound.Add("[ None ]");

		for(auto it=CurrentFile.Root().Get<gorgon::Folder>(1).Subitems.First();it.IsValid();it.Next()) {
			animsound.Add(it->GetName());
		}
	}

	void AddSound(std::string filename) {
		if(!CurrentFile.Root().GetCount()) return;

		gorgon::Sound *snd=new gorgon::Sound;
		snd->ImportWave(filename);
		if(filename.find_last_of('/')!=filename.npos) 
			filename=filename.substr(filename.find_last_of('/')+1);
		snd->SetName(filename);
		CurrentFile.Root().Get<gorgon::Folder>(1).Add(snd);
		UpdateSoundList();
	}

	void ListAnims()  {
		chlist.Animations.DeleteAll();
		for(int i=1;i<CurrentChar->GetCount();i++)
			chlist.Animations.Add(CurrentChar->Get<gorgon::Folder>(i).GetName());

		if(chlist.Animations.GetCount())
			chlist.Animations[0].Accessed();
	}


	void AddFrame() {
		for(auto it=ImageBank.GetSelectedItems().First(); it.IsValid();it.Next()) {
			animedit.Add(it->Value);
			ImageBank.Delete(*it);
		}

		SelectAnim();
		changed=true;
	}
	
	void DupFrame() {
		for(auto it=ImageBank.GetSelectedItems().First(); it.IsValid();it.Next()) {
			animedit.Add(it->Value);
			ImageBank.MoveBefore(*it, (ImageList::ItemType*)NULL);
		}

		SelectAnim();
		changed=true;
	}
	
	void DeleteSelectedFrames() {
		for(auto it=ImageBank.GetSelectedItems().First(); it.IsValid();it.Next()) {
			ImageBank.Delete(*it);
		}
	}
	
	void ClearAllFrames() {
		for(auto it=ImageBank.First(); it.IsValid();) {
			ImageBank.Delete(*it);
		}
	}
	
	void DeleteFrames(int number) {
		int i=0;
		for(auto it=ImageBank.First(); it.IsValid() && i<number;i++) {
			ImageBank.Delete(*it);
		}
	}

	void AddFrames(int number) {
		int i=0;
		for(auto it=ImageBank.First(); it.IsValid() && i<number;i++) {
			animedit.Add(it->Value);
			ImageBank.Delete(*it);
		}

		SelectAnim();
		changed=true;
		direction.SetDirection((DirectionSelector::Direction)((direction.GetDirection()+1)%4));
	}

	void DupFrames(int number) {
		for(int i=0;i<number && ImageBank.First().IsValid();i++) {
			animedit.Add(ImageBank.First()->Value);
			ImageBank.MoveBefore(ImageBank.First(), (ImageList::ItemType*)NULL);
		}

		SelectAnim();
		changed=true;
	}

	void RemoveFrame() {
		for(auto it=animedit.GetSelectedItems().Last();it.IsValid();it.Previous()) {
			if(ImageBank.First().IsValid())
				ImageBank.Insert(it->Value, ImageBank.First().CurrentPtr());
			else
				ImageBank.Add(it->Value);
			animedit.Delete(*it);
		}
		changed=true;
	}

	void ListChars()  {
		chlist.Characters.Destroy();
		for(int i=2;i<CurrentFile.Root().GetCount();i++) {
			chlist.Characters.Add(CurrentFile.Root().Get<gorgon::Folder>(i).GetName());
		}
		if(chlist.Characters.GetCount())
			chlist.Characters[0].Accessed();
	}

	void BeginImport() {
		if(FilesToImport.size()) {
			imgimport.Show(FilesToImport[FilesToImport.size()-1]);
			FilesToImport.pop_back();
		}
	}

	void SetDirectory(const std::string &dir) {
		file.SetDirectory(dir);
	}

	ImageList ImageBank;

	std::vector<std::string> FilesToImport;

protected:
	widgets::FullscreenPanel toplevel;
	widgets::Tabpanel navigation;
	FileHandler file;
	DirectionSelector direction;
	AnimationEditor animedit;
	ImageImport imgimport;
	CharList chlist;
	widgets::InlinePanel charedit;
	gorgon::File CurrentFile;
	gorgon::Folder *CurrentChar;
	gorgon::Folder *CurrentAnim;
	gorgon::Animation *CurrentDir;
	widgets::Label animdurl;
	widgets::Numberbox<int> animdur;
	widgets::Label animsoundl;
	widgets::Combobox<std::string> animsound;

	bool changed;
	enum {
		action_none,
		action_newfile,
		action_loadfile,
		action_quit
	} actionafter;

	widgets::Button ImgAdd, ImgDup, ImgAdd1, ImgAdd3, ImgAdd3s, ImgAdd4, ImgAdd6, ImgAdd7, ImgAdd8, ImgAdd9, ImgRemove, ImgDelete, ImgClear;

	void image_import() {
		int W=imgimport.Width;
		int H=imgimport.Height;
		auto &img=*imgimport.img;
		int nw=img.GetWidth()/W;
		int nh=img.GetHeight()/H;

		for(int y=0;y<nh;y++) {
			for(int x=0;x<nw;x++) {
				gorgon::Image &nimg=*new gorgon::Image(W,H);
				nimg.SetCompression(resource::Image::PNG);
				::graphics::Canvas c(nimg);
				bool isempty=true;
				for(int yy=0;yy<H;yy++) {
					for(int xx=0;xx<W;xx++) {
						c(xx,yy)=img(x*W+xx,y*H+yy);
						if(c(xx,yy).a) isempty=false;
					}
				}
				if(isempty)
					delete &nimg;
				else {
					nimg.Prepare(Main, CurrentFile);
					ImageBank.Add(&nimg);
				}
			}

			imgimport.Close();
		}

		BeginImport();
	}

};
