/* sendz.c
 * Nicholas Ingolia
 * ingolia@mit.edu
 */

#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <com_err.h>
#include <zephyr/zephyr.h>

#include "errors.h"
#include "sendz.h"

static void sendz_initialize(void);
static void sendz_send_zephyr(const char *message);
static void sendz_send_personal_zephyr(const char *victim, 
				       const char *message);
static void sendz_send_off(ZNotice_t *notice);

#define ERRMSGLEN 1024
static char errmsg[ERRMSGLEN];

static int sendz_initialized = 0;

#if 1
static const char *zclass = "sipb";
static const char *zinst = "office";
#else
static const char *zclass = "ingolia";
static const char *zinst = "test";
#endif
static const char *zopcode = "";
static const char *zsender = "not-a-fish";
static const char *zsig = "Automated Cleaning Notice";
static const char *zmessages[] = {
  "It's office cleaning time!  Please stand up and help clean the office",
  "Throw out the trash, recycle scrap paper, and rinse and recycle cans",
  "Wipe down tables and dust monitors and bookshelves",
  NULL};

static const char *zclass_debug = "ingolia";
static const char *zinst_debug = "zbot";
static const char *zopcode_debug = "";
static const char *zsender_debug = "not-a-fish";
static const char *zsig_debug = "Automated Status Information";

static void sendz_initialize(void)
{
  int err;

  err = ZInitialize();

  if (err != ZERR_NONE) {
    snprintf(errmsg, ERRMSGLEN, "sendz: Unable to initialize zephyr (%d)\n", 
	     err); 
    error(errmsg);
    return;
  }

  err = ZOpenPort(NULL);

  if (err != ZERR_NONE) {
    snprintf(errmsg, ERRMSGLEN,  "sendz: Unable to open zephyr port (%d)\n", 
	     err);
    error(errmsg);
  }

  sendz_initialized = 1;
}

void sendz_send_zephyrs()
{
  int i;

  for (i = 0; zmessages[i] != NULL; i++) {
    sendz_send_zephyr(zmessages[i]);
    sleep(2);
  }
}

void sendz_send_personal_zephyrs(const char *victim)
{
  int i;

  for (i = 0; zmessages[i] != NULL; i++) {
    sendz_send_personal_zephyr(victim, zmessages[i]);
    sleep(2);
  }
}

enum {
  buflen = 1024
};

void sendz_send_zephyr_debugging(const char *message, ...)
{
  ZNotice_t notice;
  va_list   args;
  char      buf[buflen];

  va_start(args, message);
  vsnprintf(buf, buflen, message, args);
  va_end(args);

  memset(&notice, 0, sizeof(ZNotice_t));

  notice.z_kind = ACKED;
  notice.z_port = 0;
  notice.z_class = (char *) zclass_debug;
  notice.z_class_inst = (char *) zinst_debug;
  notice.z_opcode = (char *) zopcode_debug;
  notice.z_sender = (char *) zsender_debug;
  notice.z_recipient = "";
  notice.z_default_format = "Class $class, Instance $instance at $date $time\n$message";
  notice.z_message_len = strlen(buf) + strlen(zsig_debug) + 2;
  notice.z_message = xmalloc(notice.z_message_len);
  strcpy(notice.z_message, zsig_debug);
  strcpy(notice.z_message + strlen(zsig_debug) + 1, buf);

  sendz_send_off(&notice);
}

static void sendz_send_zephyr(const char *message)
{
  ZNotice_t notice;

  memset(&notice, 0, sizeof(ZNotice_t));

  notice.z_kind = ACKED;
  notice.z_port = 0;
  notice.z_class = (char *) zclass;
  notice.z_class_inst = (char *) zinst;
  notice.z_opcode = (char *) zopcode;
  notice.z_sender = (char *) zsender;
  notice.z_recipient = "";
  notice.z_default_format = "Class $class, Instance $instance at $date $time\n$message";
  notice.z_message_len = strlen(message) + strlen(zsig) + 2;
  notice.z_message = xmalloc(notice.z_message_len);
  strcpy(notice.z_message, zsig);
  strcpy(notice.z_message + strlen(zsig) + 1, message);

  sendz_send_off(&notice);
}

static void sendz_send_personal_zephyr(const char *victim,
				       const char *message)
{
  ZNotice_t notice;

  memset(&notice, 0, sizeof(ZNotice_t));

  notice.z_kind = ACKED;
  notice.z_port = 0;
  notice.z_class = "MESSAGE";
  notice.z_class_inst = "PERSONAL";
  notice.z_opcode = (char *) zopcode;
  notice.z_sender = (char *) zsender;
  notice.z_recipient = (char *) victim;
  notice.z_default_format = "Class $class, Instance $instance at $date $time\n$message";
  notice.z_message_len = strlen(message) + strlen(zsig) + 2;
  notice.z_message = xmalloc(notice.z_message_len);
  strcpy(notice.z_message, zsig);
  strcpy(notice.z_message + strlen(zsig) + 1, message);

  sendz_send_off(&notice);
}

static void sendz_send_off(ZNotice_t *notice)
{
  int       err;
  ZNotice_t rnotice;

  if (!sendz_initialized) {
    sendz_initialize();
  }

  err = ZSendNotice(notice, ZNOAUTH);

  if (err != ZERR_NONE) {
    snprintf(errmsg, ERRMSGLEN, 
	     "sendz: Error sending zephyr notice off: %s\n", 
	     error_message(err)); 
    error(errmsg);
    return;
  }

  err = ZIfNotice(&rnotice, (struct sockaddr_in *) 0, 
		  ZCompareUIDPred, (char *) &notice->z_uid);

  if (err != ZERR_NONE) {
    ZFreeNotice(&rnotice);
    snprintf(errmsg, ERRMSGLEN,
	     "sendz: Error waiting for notice acknowledgement: %s\n",
	     error_message(err));
    return;
  }

  ZFreeNotice(&rnotice);
}













