#include "Line.h"
#include "../Game/Animation.h"
#include <vector>
#include "Rectangle.h"
#include "ResizableObject.h"
#include "BorderData.h"
#include "Placeholder.h"
#include "Listbox.h"
#include "Combobox.h"
#include "Tabpanel.h"

using namespace gge::resource;
using namespace gge::widgets;

namespace gorgon { namespace widgets{

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

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, line, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::widgets::GID::Line_Props) {
				line.mask.Load(in);
				line.IsLoopTiled  = (ReadFrom<int>(in) != 0);
				line.Orientation = (ReadFrom<int>(in)!=0 ? Line::Vertical : Line::Horizontal);

				return true;
			}

			return false;
		}, names);

		if(line.gorgon::Base::Subitems.GetCount()<3)
			line.gorgon::Base::Subitems.Add(new Animation());
		if(line.gorgon::Base::Subitems.GetCount()<2)
			line.gorgon::Base::Subitems.Add(new Animation());
		if(line.gorgon::Base::Subitems.GetCount()<1)
			line.gorgon::Base::Subitems.Add(new Animation());

		line.SetSources(dynamic_cast<Animation&>(line.gorgon::Base::Subitems[0]), dynamic_cast<Animation&>(line.gorgon::Base::Subitems[1]), dynamic_cast<Animation&>(line.gorgon::Base::Subitems[2]));

		return &line;
	}

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

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, rect, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::widgets::GID::Rectangle_Props) {
				rect.mask.Load(in);
				rect.Tiling.Center_Horizontal=ReadFrom<int>(in)!=0;
				rect.Tiling.Center_Vertical=ReadFrom<int>(in)!=0;
				rect.Tiling.Top=ReadFrom<int>(in)!=0;
				rect.Tiling.Bottom=ReadFrom<int>(in)!=0;
				rect.Tiling.Left=ReadFrom<int>(in)!=0;
				rect.Tiling.Right=ReadFrom<int>(in)!=0;

				return true;
			}

			return false;
		}, names);

		for(int i=9;i>0;i--)
			if(rect.gorgon::Base::Subitems.GetCount()<i)
				rect.gorgon::Base::Subitems.Add(new Animation());
		
		rect.SetSources(
			dynamic_cast<Animation&>(rect.gorgon::Base::Subitems[1]), 
			dynamic_cast<Animation&>(rect.gorgon::Base::Subitems[0]), 
			dynamic_cast<Animation&>(rect.gorgon::Base::Subitems[2]), 
			dynamic_cast<Animation&>(rect.gorgon::Base::Subitems[4]), 
			dynamic_cast<Animation&>(rect.gorgon::Base::Subitems[3]), 
			dynamic_cast<Animation&>(rect.gorgon::Base::Subitems[5]), 
			dynamic_cast<Animation&>(rect.gorgon::Base::Subitems[7]), 
			dynamic_cast<Animation&>(rect.gorgon::Base::Subitems[6]), 
			dynamic_cast<Animation&>(rect.gorgon::Base::Subitems[8])
		);

		return &rect;
	}

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

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, ro, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::widgets::GID::ResizableObj_Props) {
				ro.target.Load(in);
				ro.SizeController.Align=(gge::Alignment::Type)ReadFrom<int>(in);
				ro.SizeController.HorizontalTiling=(gge::graphics::SizeController2D::TilingType)ReadFrom<int>(in);
				ro.SizeController.VerticalTiling=(gge::graphics::SizeController2D::TilingType)ReadFrom<int>(in);

				return true;
			}
			else if(gid==gge::widgets::GID::ResizableObj_Names) {
				LoadNames(in, size, names, gge::widgets::GID::ResizableObj_Name);

				return true;
			}

			return false;
		}, names);

		return &ro;
	}

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

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, bd, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::widgets::GID::BorderData_Props) {
				bd.target.Load(in);
				ReadFrom(in, bd.Margins);
				ReadFrom(in, bd.Padding);
				ReadFrom(in, bd.BorderWidth);
				bd.AutoBorderWidth=ReadFrom<int>(in)!=0;

				return true;
			}
			else if(gid==gge::widgets::GID::BorderData_Names) {
				LoadNames(in, size, names, gge::widgets::GID::BorderData_Name);

				return true;
			}

			return false;
		}, names);

		return &bd;
	}

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

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, ph, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::widgets::GID::Placeholder_Props) {
				ph.Align=(gge::Alignment::Type)ReadFrom<int>(in);
				ReadFrom(in, ph.Margins);
				ph.SizingMode=(Placeholder::PlaceholderSizingMode)ReadFrom<int>(in);
				ReadFrom(in, ph.Minimum);

				return true;
			}

			return false;
		}, names);

		return &ph;
	}

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

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, lst, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::widgets::GID::Listbox_Props) {
				ReadFrom(in, lst.DefaultSize);
				lst.item.Load(in);
				lst.header.Load(in);
				lst.panel.Load(in);
				lst.altitem.Load(in);
				lst.footer.Load(in);

				return true;
			}
			else if(gid==gge::widgets::GID::Listbox_Names) {
				LoadNames(in, size, names, gge::widgets::GID::Listbox_Name);

				return true;
			}

			return false;
		}, names);

		return &lst;
	}

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

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, cmb, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::widgets::GID::Combobox_Props) {
				ReadFrom(in, cmb.DefaultSize);
				cmb.textbox.Load(in);
				cmb.listbox.Load(in);
				cmb.dropbutton.Load(in);
				ReadFrom(in, cmb.ListMargins);

				return true;
			}
			else if(gid==gge::widgets::GID::Combobox_Names) {
				LoadNames(in, size, names, gge::widgets::GID::Combobox_Name);

				return true;
			}

			return false;
		}, names);

		return &cmb;
	}

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

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, tab, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::widgets::GID::Tabpanel_Props) {
				ReadFrom(in, tab.DefaultSize);
				tab.panel.Load(in);
				tab.radio.Load(in);
				tab.placeholder.Load(in);

				return true;
			}
			else if(gid==gge::widgets::GID::Tabpanel_Names) {
				LoadNames(in, size, names, gge::widgets::GID::Tabpanel_Name);

				return true;
			}

			return false;
		}, names);

		return &tab;
	}

}}
