/* I had a code-dream last night that lead me to believe i should * add the
 * entity lang renderers and language bindings.  I know * its funny but i
 * have code-dreams all the time.  Funny thing * is when they feel right the 
 * code i create is always good.  MW */

#include <glib.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "entity.h"

/* Rational: * What am i thinking?  I'm thinking that we will be able to
 * create * some helper function that people can call when they want
 * something * simple done.  So mostly entity:<func> with be helper
 * functions. */

static GHashTable *entity_func_ht;

typedef EBuf *(*EntityFunc) (ENode * calling_node,
			     gchar * function, GSList * args);

static EBuf *
lang_entity_delete (ENode * calling_node, gchar * function, GSList * args)
{
    LangArg *arg_node;
    ENode *node;
    arg_node = (LangArg *) args->data;

    if (LANG_NODE == arg_node->type) {
	node = (ENode *) arg_node->data;
	enode_destroy (node);
    }

    return NULL;
}


static EBuf *
lang_entity_hide (ENode * calling_node, gchar * function, GSList * args)
{
    LangArg *arg_node;
    ENode *node;
    arg_node = (LangArg *) args->data;

    if (LANG_NODE == arg_node->type) {
	node = (ENode *) arg_node->data;
	enode_attrib_str (node, "visible", "false");
    }

    return NULL;
}

static EBuf *
lang_entity_hide_window (ENode * calling_node, gchar * function, GSList * args)
{
    LangArg *arg_node;
    ENode *node;
    arg_node = (LangArg *) args->data;

    if (LANG_NODE == arg_node->type) {
	node = (ENode *) arg_node->data;
	node = enode_parent (node, "window");

	if (!node)
	    return NULL;

	enode_attrib_str (node, "visible", "false");
    }

    return NULL;
}

static EBuf *
lang_entity_exit (ENode * calling_node, gchar * function, GSList * args)
{
    LangArg *arg_node;
    ENode *node;
    ENode *objnode;
    arg_node = (LangArg *) args->data;

    if (LANG_NODE == arg_node->type) {
	node = (ENode *) arg_node->data;

	if (ebuf_equal_str (node->element, "object"))
	    objnode = node;
	else
	    objnode = enode_parent (node, "object");

	if (!objnode)
	    return NULL;

	enode_destroy (objnode);
    }
    return NULL;
}

static EBuf *
lang_entity_quit (ENode * calling_node, gchar * function, GSList * args)
{
    entity_mainloop_exit ();

    /* Another brick in the -Wall */
    return NULL;
}

static EBuf *
lang_entity_version (ENode * calling_node, gchar * function, GSList * args)
{
    static EBuf *ver = NULL;

    if (!ver)
	ver = ebuf_new_with_str (VERSION);

    return (ver);
}

static EBuf *
lang_entity_languages (ENode * calling_node, gchar * function, GSList * args)
{
    static EBuf *langs = NULL;

    if (!langs) {
	GSList *tmp;
	GSList *lst = entity_supported_languages ();

	langs = ebuf_new ();

	tmp = lst;
	while (tmp) {
	    gchar *language = tmp->data;
	    ebuf_append_str (langs, language);

	    tmp = tmp->next;
	    if (tmp)
		ebuf_append_str (langs, ", ");
	}
	g_slist_free (lst);
    }

    return (langs);
}

static EBuf *
lang_entity_show_args (ENode * calling_node, gchar * function, GSList * args)
{
    LangArg *arg;
    GSList *tmp;
    ENode *node;
    EBuf *path;
    gint arg_int;
    gchar *arg_string;

    for (tmp = args; tmp; tmp = tmp->next) {
	arg = (LangArg *) tmp->data;
	if (LANG_NODE == arg->type) {
	    node = (ENode *) arg->data;
	    path = enode_path (node);
	    fprintf (stderr, "entity:%s node = %s\n", function, path->str);
	    ebuf_free (path);
	} else if (LANG_INT == arg->type) {
	    arg_int = arg->intdata;
	    fprintf (stderr, "entity:%s int = %i\n", function, arg_int);
	} else if (LANG_STRING == arg->type) {
	    arg_string = arg->data;
	    fprintf (stderr, "entity:%s string = %s\n", function, arg_string);
	} else if (LANG_BINSTRING == arg->type) {
	    fprintf (stderr, "entity:%s <binary data(not shown)>\n", function);
	}
    }

    return NULL;
}


static EBuf *
entity_function_execute (ENode * calling_node, gchar * function, GSList * args)
{
    EntityFunc func;

    func = g_hash_table_lookup (entity_func_ht, function);

    if (!func) {
	g_warning ("Undefined 'entity' function '%s'", function);
	return (NULL);
    }

    /* Just pass on the function... */
    return func (calling_node, function, args);
}

void
entity_lang_init (void)
{
    language_register ("entity", entity_function_execute);
    language_register ("e", entity_function_execute);

    entity_func_ht = g_hash_table_new (g_str_hash, g_str_equal);

    /* Setup the function string -> code ht. */
    g_hash_table_insert (entity_func_ht, "delete", lang_entity_delete);
    g_hash_table_insert (entity_func_ht, "exit", lang_entity_exit);
    g_hash_table_insert (entity_func_ht, "quit", lang_entity_quit);
    g_hash_table_insert (entity_func_ht, "hide", lang_entity_hide);
    g_hash_table_insert (entity_func_ht, "hide_window",
			 lang_entity_hide_window);
    g_hash_table_insert (entity_func_ht, "show_args", lang_entity_show_args);
    g_hash_table_insert (entity_func_ht, "version", lang_entity_version);
    g_hash_table_insert (entity_func_ht, "languages", lang_entity_languages);
}


syntax highlighted by Code2HTML, v. 0.9.1