#include <stdlib.h>
#include <string.h>
#include <libfungw/fungw.h>
#include <time.h>

/* for ACTION_HELP(()) */
#include "../../../src/action.h"

/* boilerplate: wrapper to interface fungw to our C functions */
static fgw_error_t fgws_c_call_script(fgw_arg_t *res, int argc, fgw_arg_t *argv)
{
	fgw_error_t rv;
	fgw_func_t *fnc = argv[0].val.func;
	rv = fnc->func(res, argc, argv);
	fgw_argv_free(fnc->obj->parent, argc, argv);
	return rv;
}


/* Straight wrapper around system() */
static fgw_error_t fgwc_system(fgw_arg_t *res, int argc, fgw_arg_t *argv)
{
	FGW_DECL_CTX;

	ACTION_HELP((
		"system - scripting: execute a shell command",
		"Syntax: system command",
		"",
		"Returns the integer return value of the command",
		NULL));

	FGW_ARGC_REQ_MATCH(1);
	FGW_ARG_CONV(&argv[1], FGW_STR);
	res->val.nat_int = system(argv[1].val.str);
	res->type = FGW_INT;
	return FGW_SUCCESS;
}

/* Straight wrapper around time() */
static fgw_error_t fgwc_time(fgw_arg_t *res, int argc, fgw_arg_t *argv)
{
	FGW_DECL_CTX;

	ACTION_HELP((
		"time - scripting: return seconds elapsed from epoch",
		"Syntax: time",
		NULL));

	FGW_ARGC_REQ_MATCH(0);
	res->val.nat_long = time(NULL);
	res->type = FGW_LONG;
	return FGW_SUCCESS;
}

/* Wrapper around ctime() with minimal argc logics */
static fgw_error_t fgwc_ctime(fgw_arg_t *res, int argc, fgw_arg_t *argv)
{
	time_t t;
	FGW_DECL_CTX;

	ACTION_HELP((
		"ctime - scripting: return human readablke time for seconds-from-epoch",
		"Syntax: ctime [secs]",
		"",
		"Returns a string. With no argument, uses current time.",
		NULL));

	if (argc > 1) {
		FGW_ARG_CONV(&argv[1], FGW_LONG);
		t = argv[1].val.nat_long;
	}
	else
		t = time(NULL);

	res->val.str = fgw_strdup(ctime(&t));
	res->type = FGW_STR | FGW_DYN;
	return FGW_SUCCESS;
}

/* Register all functions */
static int on_load(fgw_obj_t *obj, const char *filename, const char *opts)
{
	fgw_func_reg(obj, "system",   fgwc_system);
	fgw_func_reg(obj, "time",     fgwc_time);
	fgw_func_reg(obj, "ctime",    fgwc_ctime);
	return 0;
}

static const fgw_eng_t fgw_posix_eng = {
	"posix",            /* name of the engine; this is "lang" for load action */
	fgws_c_call_script, /* wrapper to call our functions */
	NULL,               /* init() before load, useful for scripting languages */
	on_load             /* called during the load action */
};

/* Fgwirc expects standard, puplug-loadable plugins; this is the init function
   that runs when the .so is loaded. It should register the engine, everything
   else should be done in on_load(). */
void pplg_init_fungw_posix(void)
{
	fgw_eng_reg(&fgw_posix_eng);
}
