#include "Basic.h"

#include <stdexcept>

using namespace std;
using namespace gge;
using namespace gge::utils;
using namespace gge::resource;
using namespace gge::widgets;

namespace gaming { namespace menu {

	void BasicOrganizer::Load(gge::resource::DataArray &data) {
		if(data.getInt(1)!=1)
			throw std::runtime_error("Basic menu version is not suitable.");

		layout=(Layout)data.getInt(2);
		spacing=data.getInt(3);
		align=(Alignment)data.getInt(4);
		location=data.getPoint(5);
		size=data.getInt(6);
		if(data.checkLink(7))
			panel.SetBlueprint(dynamic_cast<gge::widgets::panel::Blueprint&>(data.getLink(7)));
		cycle=(CycleStrategy)data.getInt(8);
		btn_st=dynamic_cast<gge::widgets::checkbox::Blueprint*>(data.getLinkPtr(9));
		btn_end=dynamic_cast<gge::widgets::checkbox::Blueprint*>(data.getLinkPtr(10));
		btn_mid.Clear();
		for(int i=11;i<data.GetCount();i++) {
			btn_mid.Add(dynamic_cast<gge::widgets::checkbox::Blueprint*>(data.getLinkPtr(i)));
		}
	}

	void BasicOrganizer::Setup(Menu &menu) {
		parent=&menu;

		vp.LandOn(menu.MainLayer());

		Refresh();
	}

	void BasicOrganizer::Refresh() {
		if(!parent) return;
		 
		int k=0, i=0, midcnt=0;

		for(auto button=Buttons.First();button.IsValid();button.Next()) {
			button->ClickEvent.Clear();
		}

		panel.RemoveAllWidgets();
		int distance=0;
		Button *last=NULL;

		for(auto button=parent->Buttons.First();button.IsValid();button.Next()) {
			bool forcesetbp=false;

			if(button->Visible) {
				gge::widgets::Button *btn=NULL;

				if(Buttons.GetCount()>k) {
					btn=&Buttons[k];
				} else {
					btn=new Button;
					btn->AllowFocus=false;
					forcesetbp=true;
					Buttons.Add(btn);
				}

				btn->Text=button->Text;
				btn->SetEnabled(!button->Disabled);
				btn->SetContainer(panel);
				btn->Icon=button->Icon;
				if(layout==Vertical) {
					btn->SetWidth(size);
					btn->Move(0, distance+button->Spacing*(btn->GetHeight()+spacing)/4);
					distance+=btn->GetHeight()+spacing+button->Spacing*(btn->GetHeight()+spacing)/4;
				}
				else {
					btn->SetHeight(size);
					btn->Move(distance+button->Spacing*(btn->GetWidth()+spacing)/4, 0);
					distance+=btn->GetWidth()+spacing+button->Spacing*(btn->GetWidth()+spacing)/4;
				}

				btn->ClickEvent.LinkTo(button->ClickEvent);
				last=btn;

				k++;

				if(i==0) {
					if(forcesetbp || prev_first!=btn) {
						if(btn_st)
							btn->SetBlueprint(btn_st);
						else if(btn_mid.GetCount()) {
							if(cycle==Random)
								btn->SetBlueprint(btn_mid[gge::utils::Random(0,btn_mid.GetCount())]);
							else
								btn->SetBlueprint(btn_mid[midcnt++%btn_mid.GetCount()]);
						}
						else
							btn->SetBlueprint(gge::widgets::WR.Buttons.Decorative);
					}
				}
				else if(i==parent->Buttons.GetCount()-1) {
					if(forcesetbp || prev_first==btn || prev_last==btn) {
						if(btn_mid.GetCount()) {
							if(cycle==Random)
								btn->SetBlueprint(btn_mid[gge::utils::Random(0,btn_mid.GetCount())]);
							else
								btn->SetBlueprint(btn_mid[midcnt++%btn_mid.GetCount()]);
						}
						else
							btn->SetBlueprint(gge::widgets::WR.Buttons.Decorative);
					}
				}
				else {
					if(forcesetbp || prev_last!=btn) {
						if(btn_end)
							btn->SetBlueprint(btn_end);
						else if(btn_mid.GetCount()) {
							if(cycle==Random)
								btn->SetBlueprint(btn_mid[gge::utils::Random(0,btn_mid.GetCount())]);
							else
								btn->SetBlueprint(btn_mid[midcnt++%btn_mid.GetCount()]);
						}
						else
							btn->SetBlueprint(gge::widgets::WR.Buttons.Decorative);
					}
				}

				i++;
			}
			prev_first=Buttons.First().CurrentPtr();
			prev_last=last;
		}
		if(layout==Horizontal && last) {
			panel.Resize(last->GetX()+last->GetWidth(), last->GetHeight());
			panel.Resize(last->GetX()+last->GetWidth()+panel.GetOverheadMargins().TotalX()+1, last->GetHeight()+panel.GetOverheadMargins().TotalY()+1);
		}
		else if(last) {
			panel.Resize(last->GetWidth(), last->GetY()+last->GetHeight());
			panel.Resize(last->GetWidth()+panel.GetOverheadMargins().TotalX()+1, last->GetY()+last->GetHeight()+panel.GetOverheadMargins().TotalY()+1);
			panel.Resize(last->GetWidth()+panel.GetOverheadMargins().TotalX()+1, last->GetY()+last->GetHeight()+panel.GetOverheadMargins().TotalY()+1);
		}

		Point p;
		switch(align) {
		case Topleft:
			p=location;
			break;
		case Topright:
			p=Point(vp.GetWidth()-panel.GetWidth()-location.x, location.y);
			break;
		case Bottomleft:
			p=Point(location.x, vp.GetHeight()-panel.GetHeight()-location.y);
			break;
		case Bottomright:
			p=Point(vp.GetWidth()-panel.GetWidth()-location.x, vp.GetHeight()-panel.GetHeight()-location.y);
			break;
		}

		panel.Move(p);
	}



} }
