module gedo.gui.cursor;



private import gedo.gui.component;
private import gedo.input.joystick;
private import gedo.video.rect;
private import gedo.video.color;
private import gedo.audio.sound;



alias void delegate() OnCancel;



public class Cursor
{
public:
	OnCancel onCancel;
	Joystick joystick;
	Color    color = BLUE;


	this()
	{
		joystick = null;
		onCancel = &doNothing;
		_focus   = null;

		_sounds[0] = Sound("$LIB/cursor_move.ogg");
		_sounds[1] = Sound("$LIB/cursor_click.ogg");
		_sounds[2] = Sound("$LIB/cursor_back.ogg");
	}


	Component focus()
	{
		return _focus;
	}


	void focus(Component c)
	{
		_focus = c;
	}


	void update()
	{
		assert(_focus);
		assert(joystick);

		if(joystick.buttons[0].isPushed(0))
		{
			if(auto gc = grandChild(_focus))
			{
				_focus = gc;
			}
			else if(_focus.click())
			{
				if(countParent() >= 3)
				{
					_focus = _focus.parent.parent;
				}
			}

			Source().play(_sounds[1]);
		}
		else if(joystick.buttons[1].isPushed(0))
		{
			if(!_focus.cancel())
			{
				if(countParent() >= 3)
				{
					_focus = _focus.parent.parent;
				}
				else
				{
					onCancel();
				}
			}

			Source().play(_sounds[2]);
		}
		else if(joystick.axis.asButtons()[Axis.UP].isRepeatPushed())
		{
			if(!_focus.onAxisMove(Axis.UP))
			{
				_focus = _focus.previous;
			}

			Source().play(_sounds[0]);
		}
		else if(joystick.axis.asButtons()[Axis.DOWN].isRepeatPushed())
		{
			if(!_focus.onAxisMove(Axis.DOWN))
			{
				_focus = _focus.next;
			}

			Source().play(_sounds[0]);
		}
		else if(joystick.axis.asButtons()[Axis.LEFT].isRepeatPushed())
		{
			if(!_focus.onAxisMove(Axis.LEFT))
			{
				if(_focus.parent)
				{
					foreach(child; _focus.parent.previous)
					{
						_focus = child;
						break;
					}
				}
			}

			Source().play(_sounds[0]);
		}
		else if(joystick.axis.asButtons()[Axis.RIGHT].isRepeatPushed())
		{
			if(!_focus.onAxisMove(Axis.RIGHT))
			{
				if(_focus.parent)
				{
					foreach(child; _focus.parent.next)
					{
						_focus = child;
						break;
					}
				}
			}

			Source().play(_sounds[0]);
		}

		++_time;
	}


	void draw()
	{
		assert(_focus);

		ubyte alpha = 0;
		if(_time & 32)
		{
			alpha = (31 - (_time&31)) * 8;
		}
		else
		{
			alpha = (_time & 31) * 8;
		}

		Color c = setA(color, alpha);

		Vector2D p = _focus.position[];
		for(auto parent=_focus.parent;parent;parent=parent.parent)
		{
			.gedo.math.vector.add(p, parent.position);
		}

		Rect(p, _focus.size).frame(4.0, c);
	}


	void updateWithFocus()
	{
		_focus.root.update();

		update();
	}


	void drawWithFocus()
	{
		drawChildren(_focus);

		draw();
	}


private:
	Component _focus;
	Sound[3]  _sounds;
	uint      _time;


	void doNothing()
	{
	}


	uint countParent()
	{
		uint n = 0;

		for(auto c=_focus; c.parent; c=c.parent)
		{
			++n;
		}

		return n;
	}


	static void drawChildren(Component c)
	{
		if(c.parent)
		{
			drawChildren(c.parent);

			foreach(child; c.parent)
			{
				child.draw();
			}
		}
		else
		{
			c.draw();
		}
	}


	static Component grandChild(Component a)
	{
		Component g = null;

		foreach(b; a)
		{
			g = b;
			break;
		}

		if(g)
		{
			foreach(c; g)
			{
				return c;
			}
		}

		return null;
	}
}
