#include <stdlib.h>
#include "sms_robot.h"
#include "lib_spawn.h"
#include "lprintf.h"
#include "smslib.h"

#ifdef WIN32
#	define environ _environ
#endif
#ifndef environ
	extern char **environ;
#endif

#define FALSE 0
#define TRUE !FALSE

#define MAX_ENV 100

extern int emsg(const char *format, ...);
extern int imsg(const char *format, ...);
extern int dmsg(const char *format, ...);

struct sms_robot {
	char *env[MAX_ENV],error[BFSZ],*cmdline;
	int in,out,nenv,pid;
};

struct robot_message {
	int placeholder;
};

#define trimmed(d,s) ncpy(bf,s,BFSZ-1); d = strdup(strtrm(bf));

/* should NOT return NULL as struct is needed in order to find out what errcode means */
SmsRobot *sms_robot_init(Sms *sms, RobotInit *init, int *errcode) {
	SmsRobot *robot = calloc(1,sizeof(SmsRobot));
	char bf[BFSZ];
	int i;

	trimmed(robot->cmdline,init->cmdline);
	dmsg("sms_robot: %s",robot->cmdline);

	/* -10, leave some room for env vars we need to pass so robot can process message */
	for(i = 0; i < MAX_ENV-10 && environ[i]; i++) {
		robot->env[robot->nenv++] = strdup(environ[i]);
	}
	dmsg("sms_robot: %d system env vars",robot->nenv);
	return robot;
}
SmsRobot *sms_robot_dup(SmsRobot *o) {
	SmsRobot *robot = calloc(1,sizeof(SmsRobot));
	int i;

	robot->cmdline = strdup(o->cmdline);
	dmsg("ROBOT (%s)",robot->cmdline);

	for(i = 0; i < MAX_ENV-10 && o->env[i]; i++) {
		robot->env[robot->nenv++] = strdup(o->env[i]);
	}
	dmsg("ROBOT: %d env vars",robot->nenv);

	return robot;
}
void sms_robot_free(SmsRobot **robot) {
	if (robot && *robot) {
		/* free struct stuff here */
		lib_spawn_freeenv((*robot)->env,(*robot)->nenv);
		free((*robot)->cmdline);
		/* */
		free(*robot);
		*robot = NULL;
	}
}
RobotMessage *sms_robot_wait(SmsRobot *robot, long timeout_msec, int *errcode) {
	lib_msleep(timeout_msec);
	return NULL;
}
int sms_robot_send(SmsRobot *o, void *data, char *from, char *to, char *message) {
	int i,retcode = SMS_NO_ERROR;
	SmsRobot *robot;
	char bf[BFSZ];

	robot = sms_robot_dup(o);

	/* can only add <= 10 env vars here */
	lprintf(bf,BFSZ,"%d",(i = strlen(message)));
	lib_spawn_addenv(robot->env,&robot->nenv,"SMS_LENGTH",bf);
	lib_spawn_addenv(robot->env,&robot->nenv,"SMS_FROM",from);
	lib_spawn_addenv(robot->env,&robot->nenv,"SMS_TO",to);

	dmsg("ROBOT length=(%s) from=(%s) to=(%s)",bf,from,to);
	
	robot->pid = lib_spawn(robot->cmdline,robot->env,&robot->in,&robot->out,robot->error);
	if (robot->pid == -1) retcode = SMS_SPAWN_FAILED;
	else {
		imsg("ROBOT pid=(%d)",robot->pid);
		if (!spawn_write(robot->in,message,i)) {
			spawn_error(robot->error);
			retcode = SMS_SPAWN_WRITE;
		}
		else {
			char rest[BFSZ];
			int r;

			rest[0] = '\0';
			dmsg("ROBOT read...");
			if (!spawn_gets_timed(robot->out,bf,rest,BFSZ,&r,20000)) {
				spawn_error(robot->error);
				retcode = SMS_SPAWN_READ;
			}
			else {
				imsg("ROBOT result(%s)",bf);
				if (strncmpnc(bf,"SUCCESS",7) != 0) {
					ncpy(robot->error,bf,BFSZ-1);
					retcode = SMS_SEND_FAIL;
				}
			}
		}
		dmsg("ROBOT close...");
		spawn_close_pipe(robot->out);
		spawn_close_pipe(robot->in);
		spawn_release(robot->pid);
	}

	sms_robot_free(&robot);

	dmsg("ROBOT done");

	return retcode;
}
int sms_robot_recv(SmsRobot *robot, RobotMessage *msg) {
	return SMS_NOT_SUPPORTED;
}
int sms_robot_accept(SmsRobot *robot, RobotMessage *msg, int code, char *reason) {
	return SMS_NOT_SUPPORTED;
}
int sms_robot_reject(SmsRobot *robot, RobotMessage *msg, int code, char *reason) {
	return SMS_NOT_SUPPORTED;
}
char *sms_robot_error(SmsRobot *robot, int errcode, char *bf, int bfsz) {
	if (!bf) return "";
	bf[0] = '\0';

	if (errcode == SMS_NO_ERROR) return bf;	
	else if (errcode == SMS_NOT_SUPPORTED) ncpy(bf,"This operation is not supported",bfsz-1);
	else if (errcode == SMS_SPAWN_FAILED) lprintf(bf,bfsz,"Failed to spawn process (%s)",robot->error);
	else if (errcode == SMS_SPAWN_READ) lprintf(bf,bfsz,"Failed to read from process (%s)",robot->error);
	else if (errcode == SMS_SPAWN_WRITE) lprintf(bf,bfsz,"Failed to write to process (%s)",robot->error);
	else if (errcode == SMS_SEND_FAIL) ncpy(bf,robot->error,bfsz-1);
	return bf;
}
char *sms_robot_fromip(SmsRobot *robot, RobotMessage *msg) {
	return "";
}
char *sms_robot_from(SmsRobot *robot, RobotMessage *msg) {
	return "";
}
char *sms_robot_to(SmsRobot *robot, RobotMessage *msg) {
	return "";
}
char *sms_robot_body(SmsRobot *robot, RobotMessage *msg) {
	return "";
}
void sms_robot_msgfree(SmsRobot *robot, RobotMessage **msg) {
}
