#include "reflex/ruby/window.h"


#include <rays/ruby/bounds.h>
#include <rays/ruby/painter.h>
#include "reflex/ruby/view.h"
#include "defs.h"


RUCY_DEFINE_WRAPPER_VALUE_FROM_TO(Reflex::Window)

#define THIS      to<Reflex::Window*>(self)

#define CHECK     RUCY_CHECK_OBJECT(Reflex::Window, self)

#define CALL(fun) RUCY_CALL_SUPER(THIS, fun)


static
VALUE alloc(VALUE klass)
{
	return value(new Reflex::RubyWindow<Reflex::Window>, klass);
}

static
VALUE show(VALUE self)
{
	CHECK;
	THIS->show();
	return self;
}

static
VALUE hide(VALUE self)
{
	CHECK;
	THIS->hide();
	return self;
}

static
VALUE close(VALUE self)
{
	CHECK;
	THIS->close();
	return self;
}

static
VALUE redraw(VALUE self)
{
	CHECK;
	THIS->redraw();
	return self;
}

static
VALUE set_title(VALUE self, VALUE title)
{
	CHECK;
	THIS->set_title(title.c_str());
	return title;
}

static
VALUE get_title(VALUE self)
{
	CHECK;
	return value(THIS->title());
}

static
VALUE set_frame(VALUE self)
{
	CHECK;
	THIS->set_frame(to<Rays::Bounds>(argc, argv));
	return value(THIS->frame());
}

static
VALUE get_frame(VALUE self)
{
	CHECK;
	return value(THIS->frame());
}

static
VALUE set_resizable(VALUE self, VALUE state)
{
	CHECK;
	THIS->set_resizable(to<bool>(state));
	return value(THIS->is_resizable());
}

static
VALUE is_resizable(VALUE self)
{
	CHECK;
	return value(THIS->is_resizable());
}

static
VALUE hidden(VALUE self)
{
	CHECK;
	return value(THIS->hidden());
}

static
VALUE root(VALUE self)
{
	CHECK;
	return value(THIS->root());
}

static
VALUE focus(VALUE self)
{
	CHECK;
	return value(THIS->focus());
}

static
VALUE painter(VALUE self)
{
	CHECK;
	return value(THIS->painter());
}

static
VALUE on_show(VALUE self, VALUE event)
{
	CHECK;

	RUCY_SYM(call_show_block);
	self.call(call_show_block);

	CALL(on_show(to<Reflex::Event*>(event)));
}

static
VALUE on_hide(VALUE self, VALUE event)
{
	CHECK;
	CALL(on_hide(to<Reflex::Event*>(event)));
}

static
VALUE on_close(VALUE self, VALUE event)
{
	CHECK;
	CALL(on_close(to<Reflex::Event*>(event)));
}

static
VALUE on_update(VALUE self, VALUE event)
{
	CHECK;
	CALL(on_update(to<Reflex::UpdateEvent*>(event)));
}

static
VALUE on_draw(VALUE self, VALUE event)
{
	CHECK;
	CALL(on_draw(to<Reflex::DrawEvent*>(event)));
}

static
VALUE on_move(VALUE self, VALUE event)
{
	CHECK;
	CALL(on_move(to<Reflex::FrameEvent*>(event)));
}

static
VALUE on_resize(VALUE self, VALUE event)
{
	CHECK;
	CALL(on_resize(to<Reflex::FrameEvent*>(event)));
}

static
VALUE on_key(VALUE self, VALUE event)
{
	CHECK;
	CALL(on_key(to<Reflex::KeyEvent*>(event)));
}

static
VALUE on_key_down(VALUE self, VALUE event)
{
	CHECK;
	CALL(on_key_down(to<Reflex::KeyEvent*>(event)));
}

static
VALUE on_key_up(VALUE self, VALUE event)
{
	CHECK;
	CALL(on_key_up(to<Reflex::KeyEvent*>(event)));
}

static
VALUE on_pointer(VALUE self, VALUE event)
{
	CHECK;
	CALL(on_pointer(to<Reflex::PointerEvent*>(event)));
}

static
VALUE on_pointer_down(VALUE self, VALUE event)
{
	CHECK;
	CALL(on_pointer_down(to<Reflex::PointerEvent*>(event)));
}

static
VALUE on_pointer_up(VALUE self, VALUE event)
{
	CHECK;
	CALL(on_pointer_up(to<Reflex::PointerEvent*>(event)));
}

static
VALUE on_pointer_move(VALUE self, VALUE event)
{
	CHECK;
	CALL(on_pointer_move(to<Reflex::PointerEvent*>(event)));
}

static
VALUE on_wheel(VALUE self, VALUE event)
{
	CHECK;
	CALL(on_wheel(to<Reflex::WheelEvent*>(event)));
}


static Class cWindow;

void
Init_window ()
{
	Module mReflex = rb_define_module("Reflex");

	cWindow = rb_define_class_under(mReflex, "Window", rb_cObject);
	rb_define_alloc_func(cWindow, alloc);
	rb_define_method(cWindow, "show", RUBY_METHOD_FUNC(show), 0);
	rb_define_method(cWindow, "hide", RUBY_METHOD_FUNC(hide), 0);
	rb_define_method(cWindow, "close", RUBY_METHOD_FUNC(close), 0);
	rb_define_method(cWindow, "redraw", RUBY_METHOD_FUNC(redraw), 0);
	rb_define_method(cWindow, "title=", RUBY_METHOD_FUNC(set_title), 1);
	rb_define_method(cWindow, "title", RUBY_METHOD_FUNC(get_title), 0);
	rb_define_method(cWindow, "frame=", RUBY_METHOD_FUNC(set_frame), -1);
	rb_define_method(cWindow, "frame", RUBY_METHOD_FUNC(get_frame), 0);
	rb_define_method(cWindow, "resizable=", RUBY_METHOD_FUNC(set_resizable), 1);
	cWindow.define_method("resizable?",  is_resizable);
	rb_define_method(cWindow, "hidden", RUBY_METHOD_FUNC(hidden), 0);
	rb_define_method(cWindow, "root", RUBY_METHOD_FUNC(root), 0);
	rb_define_method(cWindow, "focus", RUBY_METHOD_FUNC(focus), 0);
	rb_define_method(cWindow, "painter", RUBY_METHOD_FUNC(painter), 0);
	rb_define_method(cWindow, "on_show", RUBY_METHOD_FUNC(on_show), 1);
	rb_define_method(cWindow, "on_hide", RUBY_METHOD_FUNC(on_hide), 1);
	rb_define_method(cWindow, "on_close", RUBY_METHOD_FUNC(on_close), 1);
	rb_define_method(cWindow, "on_update", RUBY_METHOD_FUNC(on_update), 1);
	rb_define_method(cWindow, "on_draw", RUBY_METHOD_FUNC(on_draw), 1);
	rb_define_method(cWindow, "on_move", RUBY_METHOD_FUNC(on_move), 1);
	rb_define_method(cWindow, "on_resize", RUBY_METHOD_FUNC(on_resize), 1);
	rb_define_method(cWindow, "on_key", RUBY_METHOD_FUNC(on_key), 1);
	rb_define_method(cWindow, "on_key_down", RUBY_METHOD_FUNC(on_key_down), 1);
	rb_define_method(cWindow, "on_key_up", RUBY_METHOD_FUNC(on_key_up), 1);
	rb_define_method(cWindow, "on_pointer", RUBY_METHOD_FUNC(on_pointer), 1);
	rb_define_method(cWindow, "on_pointer_down", RUBY_METHOD_FUNC(on_pointer_down), 1);
	rb_define_method(cWindow, "on_pointer_up", RUBY_METHOD_FUNC(on_pointer_up), 1);
	rb_define_method(cWindow, "on_pointer_move", RUBY_METHOD_FUNC(on_pointer_move), 1);
	rb_define_method(cWindow, "on_wheel", RUBY_METHOD_FUNC(on_wheel), 1);
}


namespace Reflex
{


	Class
	window_class ()
	{
		return cWindow;
	}


}// Reflex