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

using gge::resource::ReadFrom;

namespace gorgon { namespace widgets {


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


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

		if(Font)
			SaveObject(out, *Font);
		else {
			gge::Font f;
			SaveObject(out, f);
		}
		if(ValueFont)
			SaveObject(out, *ValueFont);
		else {
			gge::Font f;
			SaveObject(out, f);
		}
		WriteTo(out, Duration);
		WriteLink(Sound, out);

		WriteLink(Border, out);
		WriteLink(Overlay, out);

		WriteLink(Symbol, out);
		WriteLink(SymbolPlace, out);
		WriteLink(TextPlace, out);
		WriteLink(ValuePlace, out);

		WriteLink(Ruler, out);
		WriteLink(Indicator, out);
		WriteLink(RulerOverlay, out);

		WriteLink(Tickmark, out);
		WriteLink(TickmarkPlace, out);
		WriteLink(TickmarkBorder, out);

		WriteEnd(out, propstart);


		WriteNames(out, *this, gge::widgets::GID::Slider_Element_Names, gge::widgets::GID::Slider_Element_Name);
		WriteSubItems(out, *this);		


		WriteEnd(out, start);
	}

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

		if(Border || Symbol || Font || Ruler || Tickmark || Indicator)
			return;

		Border				=dynamic_cast<BorderData*>(file.FindObject(border));
		Symbol				=dynamic_cast<gge::animation::RectangularGraphic2DSequenceProvider*>(file.FindObject(symbol));
		Font				=new gge::Font((gge::Font)font);
		if(!Font->Theme)
			gge::utils::CheckAndDelete(Font);
		ValueFont				=new gge::Font((gge::Font)valuefont);
		if(!ValueFont->Theme)
			gge::utils::CheckAndDelete(ValueFont);
		SymbolPlace			=dynamic_cast<Placeholder*>(file.FindObject(symbolplace));
		TextPlace			=dynamic_cast<Placeholder*>(file.FindObject(textplace));
		ValuePlace			=dynamic_cast<Placeholder*>(file.FindObject(valueplace));
		Sound				=dynamic_cast<gorgon::Sound*>(file.FindObject(sound));
		Overlay				=dynamic_cast<BorderData*>(file.FindObject(overlay));

		Ruler				=dynamic_cast<BorderData*>(file.FindObject(ruler));
		Indicator			=dynamic_cast<BorderData*>(file.FindObject(indicator));
		RulerOverlay		=dynamic_cast<BorderData*>(file.FindObject(ruleroverlay));

		Tickmark			=dynamic_cast<gge::animation::RectangularGraphic2DSequenceProvider*>(file.FindObject(tickmark));
		TickmarkPlace		=dynamic_cast<Placeholder*>(file.FindObject(tickmarkplace));
		TickmarkBorder		=dynamic_cast<BorderData*>(file.FindObject(tickmarkborder));
	}

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

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, se, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::widgets::GID::Slider_Element_Props) {
				ReadFrom<int>(in);
				int sz=ReadFrom<int>(in);
				se.font=FontInitiator::Load(file, in, sz);
				ReadFrom<int>(in);
				sz=ReadFrom<int>(in);
				se.valuefont=FontInitiator::Load(file, in, sz);

				ReadFrom(in, se.Duration);
				se.sound.Load(in);

				se.border.Load(in);
				se.overlay.Load(in);

				se.symbol.Load(in);
				se.symbolplace.Load(in);
				se.textplace.Load(in);
				se.valueplace.Load(in);

				se.ruler.Load(in);
				se.indicator.Load(in);
				se.ruleroverlay.Load(in);

				se.tickmark.Load(in);
				se.tickmarkplace.Load(in);
				se.tickmarkborder.Load(in);

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

				return true;
			}

			return false;
		}, names);

		return &se;
	}



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


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

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

		WriteLink(UpButton, out);
		WriteLink(DownButton, out);
		WriteLink(UpPlace, out);
		WriteLink(DownPlace, out);

		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::Slider_Group_Names, gge::widgets::GID::Slider_Group_Name);
		WriteSubItems(out, *this);		


		WriteEnd(out, start);
	}

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

		if(Normal)
			return;

		UpButton		=dynamic_cast<Checkbox*>(file.FindObject(upbutton));
		DownButton		=dynamic_cast<Checkbox*>(file.FindObject(downbutton));
		UpPlace			=dynamic_cast<Placeholder*>(file.FindObject(upplace));
		DownPlace		=dynamic_cast<Placeholder*>(file.FindObject(downplace));

		Normal			=dynamic_cast<SliderElement*>(file.FindObject(normal));
		Hover			=dynamic_cast<SliderElement*>(file.FindObject(hover));
		Down			=dynamic_cast<SliderElement*>(file.FindObject(down));
		Disabled		=dynamic_cast<SliderElement*>(file.FindObject(disabled));

		NormalToHover	=dynamic_cast<SliderElement*>(file.FindObject(normaltohover));
		NormalToDown	=dynamic_cast<SliderElement*>(file.FindObject(normaltodown));
		NormalToDisabled=dynamic_cast<SliderElement*>(file.FindObject(normaltodisabled));
		HoverToDown		=dynamic_cast<SliderElement*>(file.FindObject(hovertodown));

		HoverToNormal	=dynamic_cast<SliderElement*>(file.FindObject(hovertonormal));
		DownToNormal	=dynamic_cast<SliderElement*>(file.FindObject(downtonormal));
		DisabledToNormal=dynamic_cast<SliderElement*>(file.FindObject(disabledtonormal));
		DownToHover		=dynamic_cast<SliderElement*>(file.FindObject(downtohover));

		updatemapping();

	}

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

		std::vector<namecaption> names;

		LoadEntries(in, Size, file, sg, [&](GID::Type &gid, int size) -> bool {
			if(gid==gge::widgets::GID::Slider_Group_Props) {
				sg.Orientation = (gge::widgets::slider::Blueprint::OrientationType)ReadFrom<int>(in);
				sg.Focus = (gge::widgets::slider::Blueprint::FocusType)ReadFrom<int>(in);

				sg.upbutton.Load(in);
				sg.downbutton.Load(in);
				sg.upplace.Load(in);
				sg.downplace.Load(in);

				sg.normal.Load(in);
				sg.hover.Load(in);
				sg.down.Load(in);
				sg.disabled.Load(in);

				sg.normaltohover.Load(in);
				sg.normaltodown.Load(in);
				sg.normaltodisabled.Load(in);
				sg.hovertodown.Load(in);

				sg.hovertonormal.Load(in);
				sg.downtonormal.Load(in);
				sg.disabledtonormal.Load(in);
				sg.downtohover.Load(in);

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

				return true;
			}

			return false;
		}, names);

		return &sg;
	}



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


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

		WriteTo(out, (int)Pointer);
		WriteTo(out, DefaultSize);
		WriteLink(TickSound, out);
		WriteTo(out, AlphaAnimation);

		WriteEnd(out, propstart);


		WriteNames(out, *this, gge::widgets::GID::Slider_Names, gge::widgets::GID::Slider_Name);
		WriteSubItems(out, *this);		


		WriteEnd(out, start);
	}

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

		if(TickSound)
			return;

		TickSound			=dynamic_cast<Sound*>(file.FindObject(ticksound));

	}

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

		std::vector<namecaption> names;

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

				sld.Pointer=(gge::Pointer::PointerType	)ReadFrom<int>(in);
				ReadFrom(in, sld.DefaultSize);
				sld.ticksound.Load(in);
				ReadFrom(in, sld.AlphaAnimation);

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

				return true;
			}

			return false;
		}, names);

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

			sld.Mapping[g] = &g;
		}

		return &sld;
	}


}}
