#include "../File.h"
#include "../Font.h"
#include "Checkbox.h"
#include "BorderData.h"
#include <Resource/ResizableObject.h>
#include "../Extended/Sound.h"

using gge::resource::ReadFrom;

namespace gorgon { namespace widgets {


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


		auto propstart=WriteSectionStart(out, gge::widgets::GID::Checkbox_Element_Props);

		WriteTo(out, Duration);
		WriteLink(Border, out);
		if(Font)
			SaveObject(out, *Font);
		else {
			gge::Font f;
			SaveObject(out, f);
		}
		WriteLink(Lines[0], out);
		WriteLink(Lines[1], out);
		WriteLink(Lines[2], out);
		WriteLink(Symbol, out);
		WriteLink(SymbolPlace, out);
		WriteLink(TextPlace, out);
		WriteLink(IconPlace, out);
		WriteLink(Sound, out);
		WriteLink(Overlay, out);

		WriteEnd(out, propstart);


		WriteNames(out, *this, gge::widgets::GID::Checkbox_Element_Names, gge::widgets::GID::Checkbox_Element_Name);
		WriteSubItems(out, *this);		


		WriteEnd(out, start);
	}

	void CheckboxElement::Prepare(gge::GGEMain &main, File &file) {
		gorgon::Base::Prepare(main,file);

		if(Border || Lines[0] || Font)
			return;

		Border			=dynamic_cast<BorderData*>(file.FindObject(border));
		Symbol			=dynamic_cast<gge::resource::ResizableObjectProvider*>(file.FindObject(symbol));
		Font			=new gge::Font((gge::Font)font);
		if(!Font->Theme)
			gge::utils::CheckAndDelete(Font);
		SymbolPlace		=dynamic_cast<Placeholder*>(file.FindObject(symbolplace));
		TextPlace		=dynamic_cast<Placeholder*>(file.FindObject(textplace));
		IconPlace		=dynamic_cast<Placeholder*>(file.FindObject(iconplace));
		Sound			=dynamic_cast<gorgon::Sound*>(file.FindObject(sound));
		Overlay			=dynamic_cast<BorderData*>(file.FindObject(overlay));

		for(int i=0;i<3;i++) {
			Lines[i]	=dynamic_cast<CheckboxLine*>(file.FindObject(lines[i]));
		}
	}

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

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, ce, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::widgets::GID::Checkbox_Element_Props) {
				ReadFrom(in, ce.Duration);

				ce.border.Load(in);

				ReadFrom<int>(in);//gid
				int sz=ReadFrom<int>(in);//size
				ce.font=gorgon::FontInitiator::Load(file, in, sz);

				ce.lines[0].Load(in);
				ce.lines[1].Load(in);
				ce.lines[2].Load(in);
				ce.symbol.Load(in);
				ce.symbolplace.Load(in);
				ce.textplace.Load(in);
				ce.iconplace.Load(in);
				ce.sound.Load(in);
				ce.overlay.Load(in);

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

				return true;
			}

			return false;
		}, names);

		return &ce;
	}



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


		auto propstart=WriteSectionStart(out, gge::widgets::GID::Checkbox_Group_Props);

		WriteTo(out, (int)State);
		WriteTo(out, (int)Focus);

		WriteLink(Normal, out);
		WriteLink(Hover, out);
		WriteLink(Down, out);
		WriteLink(Disabled, out);

		WriteLink(NormalToHover, out);
		WriteLink(NormalToDown, out);
		WriteLink(NormalToDisabled, out);
		WriteLink(HoverToDown, out);

		WriteLink(HoverToNormal, out);
		WriteLink(DisabledToNormal, out);
		WriteLink(DisabledToNormal, out);
		WriteLink(DownToHover, out);

		WriteEnd(out, propstart);


		WriteNames(out, *this, gge::widgets::GID::Checkbox_Group_Names, gge::widgets::GID::Checkbox_Group_Name);
		WriteSubItems(out, *this);		


		WriteEnd(out, start);
	}

	void CheckboxGroup::Prepare(gge::GGEMain &main, File &file) {
		gorgon::Base::Prepare(main,file);

		if(Normal)
			return;

		Normal			=dynamic_cast<CheckboxElement*>(file.FindObject(normal));
		Hover			=dynamic_cast<CheckboxElement*>(file.FindObject(hover));
		Down			=dynamic_cast<CheckboxElement*>(file.FindObject(down));
		Disabled		=dynamic_cast<CheckboxElement*>(file.FindObject(disabled));
		
		NormalToHover	=dynamic_cast<CheckboxElement*>(file.FindObject(normaltohover));
		NormalToDown	=dynamic_cast<CheckboxElement*>(file.FindObject(normaltodown));
		NormalToDisabled=dynamic_cast<CheckboxElement*>(file.FindObject(normaltodisabled));
		HoverToDown		=dynamic_cast<CheckboxElement*>(file.FindObject(hovertodown));
		
		HoverToNormal	=dynamic_cast<CheckboxElement*>(file.FindObject(hovertonormal));
		DownToNormal	=dynamic_cast<CheckboxElement*>(file.FindObject(downtonormal));
		DisabledToNormal=dynamic_cast<CheckboxElement*>(file.FindObject(disabledtonormal));
		DownToHover		=dynamic_cast<CheckboxElement*>(file.FindObject(downtohover));

		updatemapping();

	}

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

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, cg, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::widgets::GID::Checkbox_Group_Props) {
				cg.State = (gge::widgets::checkbox::Blueprint::StateMode)ReadFrom<int>(in);
				cg.Focus = (gge::widgets::checkbox::Blueprint::FocusType)ReadFrom<int>(in);
				
				cg.normal.Load(in);
				cg.hover.Load(in);
				cg.down.Load(in);
				cg.disabled.Load(in);
				
				cg.normaltohover.Load(in);
				cg.normaltodown.Load(in);
				cg.normaltodisabled.Load(in);
				cg.hovertodown.Load(in);
				
				cg.hovertonormal.Load(in);
				cg.downtonormal.Load(in);
				cg.disabledtonormal.Load(in);
				cg.downtohover.Load(in);

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

				return true;
			}

			return false;
		}, names);

		return &cg;
	}



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


		auto propstart=WriteSectionStart(out, gge::widgets::GID::Checkbox_Line_Props);
		
		WriteLink(Border,out);
		WriteTo(out, (int)Contents.t);
		WriteTo(out, (int)WidthMode);
		WriteTo(out, (int)HeightMode);
		WriteTo(out, Height);
		WriteTo(out, (int)Align);

		WriteEnd(out, propstart);


		WriteNames(out, *this, gge::widgets::GID::Checkbox_Line_Names, gge::widgets::GID::Checkbox_Line_Name);
		WriteSubItems(out, *this);		


		WriteEnd(out, start);
	}

	void CheckboxLine::Prepare(gge::GGEMain &main, File &file) {
		gorgon::Base::Prepare(main,file);

		if(Border)
			return;

		Border				=dynamic_cast<BorderData*>(file.FindObject(border));
	}

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

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, cl, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::widgets::GID::Checkbox_Line_Props) {

				cl.border.Load(in);
				cl.Contents		=(Checkbox::LineContents)ReadFrom<int>(in);
				cl.WidthMode	=(Checkbox::SizingMode  )ReadFrom<int>(in);
				cl.HeightMode	=(Checkbox::HeightType  )ReadFrom<int>(in);
				ReadFrom(in,    cl.Height);
				cl.Align		=(gge::Alignment::Type        )ReadFrom<int>(in);

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

				return true;
			}

			return false;
		}, names);

		return &cl;
	}



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


		auto propstart=WriteSectionStart(out, gge::widgets::GID::Checkbox_Props);

		WriteTo(out, (int)Pointer);
		WriteTo(out, (int)States);
		WriteTo(out, DefaultSize);
		WriteTo(out, AlphaAnimation);

		WriteEnd(out, propstart);


		WriteNames(out, *this, gge::widgets::GID::Checkbox_Names, gge::widgets::GID::Checkbox_Name);
		WriteSubItems(out, *this);		


		WriteEnd(out, start);
	}

	void Checkbox::Prepare(gge::GGEMain &main, File &file) {
		gorgon::Base::Prepare(main, file);

		for(auto it=gorgon::Base::Subitems.First();it.IsValid();it.Next()) {
			CheckboxGroup &g=dynamic_cast<CheckboxGroup &>(*it);

			Mapping[g] = &g;
		}
	}

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

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, chk, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::widgets::GID::Checkbox_Props) {

				chk.Pointer=(gge::Pointer::PointerType	)ReadFrom<int>(in);
				chk.States =(Checkbox::StateNumbers)ReadFrom<int>(in);
				ReadFrom(in, chk.DefaultSize);
				ReadFrom(in, chk.AlphaAnimation);

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

				return true;
			}

			return false;
		}, names);

		return &chk;
	}


}}
