#include <gtk/gtk.h>
#include <gjs/gjs.h>

#define JS_CLASS "\
const Lang    = imports.lang; \
const GObject = imports.gi.GObject; \
const Gtk     = imports.gi.Gtk; \
\
const MyBox = new Lang.Class({ \
    Name: 'MyBox', \
    Extends: Gtk.Box, \
    Properties: { \
        'string-property': GObject.ParamSpec.string('string-property', 'Short description', \
            'Longer description', GObject.ParamFlags.READWRITE | GObject.ParamFlags.CONSTRUCT, \
            ''), \
    }, \
    _init: function (props={}) { \
        this.parent (props); \
        print ('MyBox init!'); \
	this.myvar = 'Test value'; \
    }, \
}); \
var a = new MyBox (); \
"

static gboolean
_gtype_class_cache_func (gpointer cache_data, GTypeClass *g_class)
{
  GType type = G_TYPE_FROM_CLASS (g_class);

  g_message ("%s %"G_GSIZE_FORMAT" %s", __func__, type, g_type_name (type));

  return FALSE;
}

/* gcc -o gjs-test -Wall -O0 -g `pkg-config gtk+-3.0 gjs-1.0 --cflags --libs` gjs-test.c */
int
main (int argc, char **argv)
{
  GtkWidget *win, *box, *label;
  GjsContext  *context;
  int exit_status = 0;
  GError *error = NULL;
  GType foo_type;
  GTypePlugin *plugin;

  gtk_init (&argc, &argv);

  g_type_add_class_cache_func (NULL, _gtype_class_cache_func);

  /* Create new GJS context */
  context = gjs_context_new ();

  /* Define a GtkWidget derived class in JS */
  gjs_context_eval (context, JS_CLASS, -1, NULL, &exit_status, &error);
  if (error)
    {
      g_warning ("GJS eval failed: %s", error->message);
      g_error_free (error);
    }

  win = gtk_window_new (GTK_WINDOW_TOPLEVEL);

  foo_type = g_type_from_name ("Gjs_MyBox");
  g_assert (foo_type != G_TYPE_INVALID);

  g_type_ensure (foo_type);

  plugin = g_type_get_plugin (foo_type);
  g_assert (plugin);

  g_assert (g_type_is_a (foo_type, GTK_TYPE_BOX));

  g_message ("MyBox type #%"G_GSIZE_FORMAT" name: %s", foo_type, g_type_name (foo_type));

  box = g_object_new (foo_type, "string-property", "test", NULL);

  label = gtk_label_new ("This is a regular GtkLabel inside a GtkBox derived container defined in GJS");

  gtk_container_add (GTK_CONTAINER (box), label);
  gtk_container_add (GTK_CONTAINER (win), box);

  gtk_widget_show_all (GTK_WIDGET (win));

  gtk_main ();

  return 0;
}


