#include "rays/ruby/image.h"


#include "rays/ruby/color_space.h"
#include "rays/ruby/bitmap.h"
#include "rays/ruby/painter.h"
#include "defs.h"


RUCY_DEFINE_VALUE_FROM_TO(Rays::Image)

#define THIS  to<Rays::Image*>(self)

#define CHECK RUCY_CHECK_OBJECT(Rays::Image, self)


static
VALUE alloc(VALUE klass)
{
	return new_type<Rays::Image>(klass);
}

static
VALUE initialize(VALUE self)
{
	RUCY_CHECK_OBJ(Rays::Image, self);
	check_arg_count(__FILE__, __LINE__, "Image#initialize", argc, 1, 2, 3, 4);

	if (argv[0].is_kind_of(Rays::bitmap_class()))
	{
		check_arg_count(__FILE__, __LINE__, "Image#initialize", argc, 1, 2);

		const Rays::Bitmap* bitmap = to<Rays::Bitmap*>(argv[0]);
		if (!bitmap)
			argument_error(__FILE__, __LINE__);

		float pixel_density = (argc >= 2) ? to<float>(argv[1]) : 1;
		*THIS = Rays::Image(*bitmap, pixel_density);
	}
	else
	{
		check_arg_count(__FILE__, __LINE__, "Image#initialize", argc, 2, 3, 4);

		int width           = to<int>(argv[0]);
		int height          = to<int>(argv[1]);
		Rays::ColorSpace cs = (argc >= 3) ? to<Rays::ColorSpace>(argv[2]) : Rays::RGBA;
		float pixel_density = (argc >= 4) ? to<float>(argv[3]) : 1;
		*THIS = Rays::Image(width, height, cs, pixel_density);
	}

	return self;
}

static
VALUE initialize_copy(VALUE self, VALUE obj)
{
	RUCY_CHECK_OBJ(Rays::Image, self);

	*THIS = to<Rays::Image&>(obj).dup();
	return self;
}

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

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

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

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

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

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

static
VALUE save(VALUE self, VALUE path)
{
	CHECK;
	Rays::save_image(*THIS, path.c_str());
	return self;
}


static
VALUE load(VALUE self)
{
	check_arg_count(__FILE__, __LINE__, "Image.load", argc, 1);

	return value(Rays::load_image(argv[0].c_str()));
}


static Class cImage;

void
Init_image ()
{
	Module mRays = rb_define_module("Rays");

	cImage = rb_define_class_under(mRays, "Image", rb_cObject);
	rb_define_alloc_func(cImage, alloc);
	rb_define_private_method(cImage, "initialize", RUBY_METHOD_FUNC(initialize), -1);
	rb_define_private_method(cImage, "initialize_copy", RUBY_METHOD_FUNC(initialize_copy), 1);
	rb_define_method(cImage, "width", RUBY_METHOD_FUNC(width), 0);
	rb_define_method(cImage, "height", RUBY_METHOD_FUNC(height), 0);
	rb_define_method(cImage, "color_space", RUBY_METHOD_FUNC(color_space), 0);
	rb_define_method(cImage, "pixel_density", RUBY_METHOD_FUNC(pixel_density), 0);
	rb_define_method(cImage, "painter", RUBY_METHOD_FUNC(painter), 0);
	rb_define_method(cImage, "bitmap", RUBY_METHOD_FUNC(bitmap), 0);
	rb_define_method(cImage, "save", RUBY_METHOD_FUNC(save), 1);
	rb_define_function(cImage, "load", RUBY_METHOD_FUNC(load), -1);
}


namespace Rays
{


	Class
	image_class ()
	{
		return cImage;
	}


}// Rays