#ifndef RUBYOBJECTS_H
#define RUBYOBJECTS_H

// K-3D
// Copyright (c) 1995-2004, Timothy M. Shead
//
// Contact: tshead@k-3d.com
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/** \file
		\brief Declares classes for implementing a scripting object model in Ruby
		\author Anders Dahnielson (anders@dahnielson.com)
		\author Romain Behar (romainbehar@yahoo.com)
*/

#include "rubymacros.h"

#include <k3dsdk/result.h>

// Forward declarations ...
namespace k3d { class icommand_node; }
namespace k3d { class idocument; }
namespace k3d { class iobject; }
namespace k3d { class iobject_collection; }
namespace k3d { class irender_frame; }
namespace k3d { class irender_job; }
namespace k3d { class iuser_interface; }

/////////////////////////////////////////////////////////////////////////////
// Ruby skeleton

// Template for implementing a scripting object model in Python
template<class InterfaceType, class BaseType>
class RubySkeleton
{
public:
	typedef RubySkeleton<InterfaceType, BaseType> Skeleton;
	typedef BaseType Owner;

	static VALUE RBClass;

	static VALUE Create(InterfaceType* const Interface)
	{
		// Sanity checks ...
		assert_warning(Interface);

		// Wrap the 'Interface' into a class and initialize
		VALUE tdata = Data_Wrap_Struct(RBClass, 0, free, Interface);
		rb_obj_call_init(tdata, 0, 0);
		return tdata;
	}

	static InterfaceType* Interface(VALUE object)
	{
		// Unwrap the 'Interface' from class
		if (TYPE(object) == T_DATA) {
			InterfaceType *ptr;
			Data_Get_Struct(object, InterfaceType, ptr);
			return ptr;
		}
		else
			return 0;
	}

	template<class NewInterfaceType, class NewActualType>
	static VALUE DynamicCast(VALUE const Object)
	{
		NewInterfaceType* const i = dynamic_cast<NewInterfaceType*>(Interface(Object));
		return_val_if_fail(i, RBVAL_FALSE);

		return NewActualType::Create(i);
	}

};

/////////////////////////////////////////////////////////////////////////////
// CRubyObject

class CRubyObject :
	public RubySkeleton<k3d::iobject, CRubyObject>
{
public:
	static void CreateClass();

	static VALUE initialize(VALUE self);

	static VALUE GetDocument(VALUE self);
	static VALUE GetName(VALUE self);
	static VALUE SetName(VALUE self, VALUE str_name);
	static VALUE EditObject(VALUE self);
};

/////////////////////////////////////////////////////////////////////////////
// CRubyDocument

class CRubyDocument :
	public RubySkeleton<k3d::idocument, CRubyDocument>
{
public:
	static void CreateClass();

	static VALUE initialize(VALUE self);

	static VALUE GetApplication(VALUE self);
	static VALUE GetPath(VALUE self);
	static VALUE Import(VALUE self, VALUE str_file, VALUE str_format);
	static VALUE Export(VALUE self, VALUE str_file, VALUE str_format);
	static VALUE Save(VALUE self, VALUE str_file);
	static VALUE StartChangeSet(VALUE self);
	static VALUE FinishChangeSet(VALUE self, VALUE str_string);
	static VALUE RedrawAll(VALUE self);

	static VALUE CreateObject(VALUE self, VALUE str_name);
	static VALUE Objects(VALUE self);
	static VALUE GetObject(VALUE self, VALUE str_name);
	static VALUE DeleteObject(VALUE self, VALUE str_name);
};

/////////////////////////////////////////////////////////////////////////////
// CRubyCommandNode

class CRubyCommandNode :
	public RubySkeleton<k3d::icommand_node, CRubyCommandNode>
{
public:
	static void CreateClass();

	static VALUE initialize(VALUE self);

	static VALUE Command(VALUE self, VALUE str_command, VALUE str_arguments);
	static VALUE GetNode(VALUE self, VALUE str_name);
	static VALUE GetProperty(VALUE self, VALUE str_name);
	static VALUE SetProperty(VALUE self, VALUE str_name, VALUE argument);
	static VALUE GetChildren(VALUE self);
	static VALUE GetProperties(VALUE self);
};

/////////////////////////////////////////////////////////////////////////////
// CRubyUserInterface

class CRubyUserInterface :
	public RubySkeleton<k3d::iuser_interface, CRubyUserInterface>
{
public:
	static void CreateClass();

	static VALUE initialize(VALUE self);

	static VALUE BrowserNavigate(VALUE self, VALUE str_url);
	static VALUE Message(VALUE self, VALUE str_message, VALUE str_title);
	static VALUE QueryMessage(VALUE self, VALUE str_message, VALUE str_title, VALUE arr_buttons);
	static VALUE ErrorMessage(VALUE self, VALUE str_message, VALUE str_title);
	static VALUE GetFilePath(VALUE self, VALUE string_type, VALUE string_prompt, VALUE bool_overwrite, VALUE string_oldpath);
};

/////////////////////////////////////////////////////////////////////////////
// CRubyScriptEngines

class CRubyScriptEngines
{
public:
	static void CreateClass();

	static VALUE RBClass;
	static VALUE initialize(VALUE self);

	static VALUE PlayFile(VALUE self, VALUE string_filename);
};

/////////////////////////////////////////////////////////////////////////////
// CRubyApplication

class CRubyApplication
{
public:
	static void CreateModule();

	static VALUE RBModule;
	static VALUE initialize(VALUE self);

	static VALUE GetUI(VALUE self);
	static VALUE GetScripts(VALUE self);
	static VALUE GetDocuments(VALUE self);
	static VALUE GetDialogTemplatesPath(VALUE self);
	static VALUE GetShaderCachePath(VALUE self);
	static VALUE GetSharePath(VALUE self);
	static VALUE GetTutorialsPath(VALUE self);
	static VALUE Close(VALUE self);
	static VALUE NewDocument(VALUE self);
	static VALUE OpenDocument(VALUE self, VALUE str_file);
	static VALUE CloseDocument(VALUE self, VALUE doc_document);
	static VALUE CommandNode(VALUE self, VALUE str_nodepath);
};

#endif // RUBYOBJECTS_H


