

#include <flare_gui/widget.h>
#include <flare_gui/widget_parent.h>
#include <allegro_flare/allegro_flare.h>
#include <flare_gui/widget_screen.h>




FGUIWidget::FGUIWidget(FGUIParent *parent, FGUICollisionArea *collision_area)
	: parent(parent)
	, collision_area(collision_area)
	, mouse_down_on_over(false)
	, mouse_over(false)
	, focused(false)
	, dragging(false)
{
//	set("FGUIWIDGETTYPE", "FGUIWidget");
	if (parent) parent->attach_widget(this);
	num_active_widgets++;
}




FGUIWidget::~FGUIWidget()
{
	delete collision_area;
	if (parent) parent->detach_widget(this);
	num_active_widgets--;
}





placement2d *FGUIWidget::gimmie_placement()
{
	return &collision_area->placement;
}





bool FGUIWidget::is_focused()
{
	return focused;
}





FGUIWidget *FGUIWidget::gimmie_super_parent()
{
	FGUIWidget *widget = this;
	while(widget->parent) widget = widget->parent;
	return static_cast<FGUIWidget *>(widget);
}




FGUIScreen *FGUIWidget::gimmie_super_screen()
{
	return static_cast<FGUIScreen *>(gimmie_super_parent());
}




#include <allegro_flare/motion_control.h>

MotionManager *FGUIWidget::gimmie_motion()
{
	return &gimmie_super_screen()->motion;
}




FontBin *FGUIWidget::gimmie_fonts()
{
	return &gimmie_super_screen()->fonts;
}




void FGUIWidget::bring_to_front()
{
	if (!parent) return;
	for (unsigned i=0; i<parent->children.size(); i++)
	{
		if (parent->children[i] == this)
		{
			parent->children.erase(parent->children.begin() + i);
			parent->children.push_back(this);
			return;
		}
	}
}




void FGUIWidget::send_message_to_parent(std::string message)
{
	if (parent) parent->receive_message(message);
}




void FGUIWidget::primary_timer_func()
{
	on_timer();
}




void FGUIWidget::draw_func()
{
	placement2d *placement = gimmie_placement();
	placement->start_transform();

	on_draw();
	
	// draws the focus rectangle if it's focused
	if (focused && gimmie_super_screen()->draw_focused_outline)
		al_draw_rounded_rectangle(0, 0, collision_area->placement.w, collision_area->placement.h, 4, 4, color::color(color::fuchsia, 0.6+0.4*sin(af::time_now*3)), 2);

	placement->restore_transform();

	// draws the collision shape (for debugging)
	//collision_area->draw_bounding_area();
}



// widget developer functions:
void FGUIWidget::mouse_axes_func(float x, float y, float dx, float dy)
{
	bool mouse_over_now = collision_area->collides(x, y);
	if (parent && parent->mouse_blocked) mouse_over_now = false;

	if (mouse_over_now && !mouse_over) on_mouse_enter();
	else if (!mouse_over_now && mouse_over) on_mouse_leave();

	mouse_over = mouse_over_now;
	if (parent && mouse_over) parent->mouse_blocked = true;

	on_mouse_move(x, y, dx, dy);
	if (mouse_down_on_over)
	{
		dragging = true;
		on_drag(x, y, dx, dy);
	}
}



void FGUIWidget::mouse_down_func()
{
	if (mouse_over)
	{
		mouse_down_on_over = true;
		on_mouse_down();
		focused = true;
		on_focus();
	}
	else
	{
		focused = false;
		on_blur();
	}
}



void FGUIWidget::mouse_up_func()
{
	if (mouse_over && mouse_down_on_over) on_click();
	mouse_down_on_over = false;
	if (dragging)
	{
		dragging = false;
		on_drop();
	}
	on_mouse_up();
}



void FGUIWidget::key_down_func()
{
	on_key_down();
}


void FGUIWidget::key_up_func()
{
	on_key_up();
}


void FGUIWidget::key_char_func()
{
	on_key_char();
}


// user functions:
void FGUIWidget::on_focus() {}
void FGUIWidget::on_blur() {}
void FGUIWidget::on_drop() {}

void FGUIWidget::on_mouse_enter() {}
void FGUIWidget::on_mouse_leave() {}
void FGUIWidget::on_mouse_move(float x, float y, float dx, float dy) {}
void FGUIWidget::on_mouse_down() {}
void FGUIWidget::on_mouse_up() {}
void FGUIWidget::on_click() {}

void FGUIWidget::on_key_down() {}
void FGUIWidget::on_key_up() {}
void FGUIWidget::on_key_char() {}

void FGUIWidget::on_timer() {}
void FGUIWidget::on_draw()
{
	placement2d *placement = gimmie_placement();
	al_draw_rounded_rectangle(0, 0, placement->w, placement->h, 4, 4, color::color(color::aliceblue, 0.2), 2.0);
}
void FGUIWidget::on_drag(float x, float y, float dx, float dy) {}



int FGUIWidget::num_active_widgets = 0;

int FGUIWidget::get_num_active_widgets()
{
	return num_active_widgets;
}



void FGUIWidget::set_as_focused()
	// iterates through all siblings and sets all parent's children to unfocused.
	// if the widget is not already focused, then set to focused and on_focus() is called
{
	if (parent && parent->set_focus_to(this))
		this->on_focus();
}



void FGUIWidget::set_as_unfocused()
	// if the widget is currently focused, chages the state to !focused and calls on_blur().
{
	if (is_focused())
	{
		focused=false;
		on_blur();
	}
}

