/*
				post.c

	       written by Ken Stevens for chainsaw 3.0

DESCRIPTION:
This program gives you a mail-like interface for reading your telegrams.

INSTALLATION:
This file should be called "post.c" and should be placed in your empire
directory (the directory you specified on the "addgame" line in your
.eifrc file)

In unix, type:
  make post

HOW TO RUN IT:
In your .eifrc file, add the line:
alias mail "read >> teles; &y; @post"

Then in eif, when you want to use this interface for reading your telegrams,
just type "mail".

BUG REPORTS:
mail your bug-reports and comments to:
stevens@math.utoronto.ca
*/

#include <stdio.h>
#define MAX_LINE_LENGTH   100
#define MAX_COMMAND_LENGTH   800
#define MAX_TELEGRAM_LENGTH (1024 + 2*MAX_LINE_LENGTH)
#define MAX_NUM_TELEGRAMS   50

char telhead[MAX_NUM_TELEGRAMS][MAX_LINE_LENGTH];
#define UNKNOWN  0
#define PROD     1
#define BULL     2
#define TELE     3

typedef struct mail_header {
  int type;
  char status;
  char *type_mark[5];
  char from[13];
  char date[20];
  char subj[30];
} Mail_header;
  
Mail_header head[MAX_NUM_TELEGRAMS];
char *body[MAX_NUM_TELEGRAMS][MAX_TELEGRAM_LENGTH][MAX_LINE_LENGTH];
int numlines[MAX_NUM_TELEGRAMS];
int start_message = 0;
int new_message = 0;

main()
{
  FILE *telfile;
  char filename[8];    
  int n;

  telfile = fopen("teles", "r");
  if (!telfile) {
    puts("No telegram file.\n");
    exit(-1);
  }
  n = read_telegrams(telfile);
  fclose(telfile);
  print_headers(n,start_message);
  if (prompt(n)) {
    printf("Saving changes to telegrams...\n");
    telfile = fopen("teles", "w");
    if (!telfile) {
      puts("No write to telegram file.\n");
      exit(-1);
    }
    write_telegrams(telfile, n);
    fclose(telfile);
  }
}

char *clean_head(s)
     char *s;
{
  int i;

  if (strlen(s))
    for (i = strlen(s) - 1; i && s[i] == ' ' || s[i] == '\n'; s[i--] = '\0');
  return s;
}

read_telegrams(telfile)
     FILE *telfile;
{
  int n = 0;
  char s[MAX_LINE_LENGTH];
  char from[MAX_LINE_LENGTH];
  int  cnum;
  char weekday[MAX_LINE_LENGTH];
  char month[MAX_LINE_LENGTH];
  int date;
  char time[MAX_LINE_LENGTH];
  int year, money;
  char dummy[MAX_LINE_LENGTH];
  
  fgets(s, MAX_LINE_LENGTH, telfile);
  while (!feof(telfile) && n < MAX_NUM_TELEGRAMS) {
    if (!strcmp(s, "read \n") ||
	!strcmp(s, "y\n") ||
	!strcmp(s, "You have a new telegram waiting ...\n") ||
	!strcmp(s, "Into the shredder, boss? y\n") ||
	!strcmp(s, "No telegrams for you at the moment...\n"));
    else if (*s == '>') {
      ++n;
      head[n].status = 'N';
      head[n].subj[0] = '\0';
      head[n].type = UNKNOWN;
      numlines[n] = 0;
      if (sscanf(s, "> Production Report %s %s %s %d %s %d",
		 dummy,weekday,month,&date,time,&year)==6) {
	head[n].type = PROD;
	strcpy(head[n].type_mark,"----");
	strcpy(head[n].from, "Production");
	sprintf(head[n].date, "%3s %3s %2d %8s", weekday, month, date, time);
      }
      else if (sscanf(s, "> BULLETIN from %s (#0) %s %s %s %d %s %d",
		      dummy,dummy,weekday,month,&date,time,&year)==7) {
	head[n].type = BULL;
	strcpy(head[n].type_mark,"*");
	strcpy(head[n].from, "BULLETIN");
	sprintf(head[n].date, "%3s %3s %2d %8s", weekday, month, date, time);
      }
      else if (sscanf(s, "> Telegram from %s (#%d) %s %s %s %d %s %d",
		      from,&cnum,dummy,weekday,month,&date,time,&year)==8) {
	from[strlen(from)-1] = '\0';
	head[n].type = TELE;
	sprintf(head[n].type_mark,"#%d", cnum);
	strncpy(head[n].from, from, 12);
	sprintf(head[n].date, "%3s %3s %2d %8s", weekday, month, date, time);
      }
      if (s[strlen(s) - 2] == ' ')
	if (s[strlen(s) - 3] == ' ') {
	  head[n].status = 'U';
	  if (!start_message && !new_message)
	    start_message = n;
	}
	else
	  head[n].status = 'R';
      else if (!new_message) {
	start_message = n;
	new_message = 1;
      }
      strncpy(telhead[n], clean_head(s), MAX_LINE_LENGTH);
    }
    else if (n) {
      strncpy(body[n][numlines[n]++], s, MAX_LINE_LENGTH);      
      if (head[n].type == PROD) {
	if (sscanf(s, "money delta was $%d for this update", &money) == 1)
	  sprintf(head[n].subj, "money delta:  $%d", money);
      }
      else if (head[n].type == BULL) {
	if (!*head[n].subj)
	  if (index(s, '(')) {
	    strncpy(head[n].subj, s, 30);
	    head[n].subj[strlen(head[n].subj) - 1] = '\0';
	  }
      }
      else if (!*head[n].subj)
	if (*s && strcmp(s, "\n")) {
	  strncpy(head[n].subj, s, 30);
	  head[n].subj[strlen(head[n].subj) - 1] = '\0';
	}
    }
    fgets(s, MAX_LINE_LENGTH, telfile);
  }
  if (!start_message)
    start_message = 1;
  return n;
}

print_headers(n,cm)
     int n,cm;
{
  int m;
  
  for (m = 1; m <= n; ++m)
    printf("%3d %c%c %4s %-12s %19s %-30s\n",
	   m,
	   m == cm?'>':' ',
	   head[m].status,
	   head[m].type_mark,
	   head[m].from,
	   head[m].date,
	   head[m].subj);
}

write_telegrams(telfile, n)
     FILE *telfile;
     int n;
{
  int m, i;

  for (m = 1; m <= n; ++m) {
    if (head[m].status != 'D') {
      if (head[m].status == 'R' || head[m].status == ' ')
	fprintf(telfile, "%s \n", telhead[m]);
      else
	fprintf(telfile, "%s  \n", telhead[m]);
      for (i = 0; i < numlines[m]; ++i)
	fprintf(telfile, "%s", body[m][i]);
    }
  }
}

prompt(n)
     int n;
{
  char s[MAX_COMMAND_LENGTH];
  int newm;
  int m = start_message;

  if (m > n)
    m = n;
  printf("(%d/%d): ", m, n);
  fgets(s, MAX_LINE_LENGTH, stdin);
  clean_head(s);
  while(!feof(stdin) &&
	strcmp(s, "q") &&
	strcmp(s, "x")) {
    if (!strcmp(s, "h"))
      print_headers(n,m);
    else if (!strcmp(s, "d")) {
      head[m].status = 'D';
      ++m;
    }
    else if (*s == 'd')
      process_delete(s + 1, n,0);
    else if (*s == 'u')
      process_delete(s + 1, n,1);
    else if (sscanf(s, "%d", &newm) == 1)
      if (newm < 1 || newm > n)
	printf("Bad message number: %d\n", newm);
      else
	print_message(m = newm);
    else if (!strcmp(s, ""))
      if (m == n)
	puts("No more messages.");
      else {
	if (head[m].status == ' ')
	  ++m;
	print_message(m);
      }
    else
      mail_help();
    
    printf("(%d/%d): ", m, n);
    fgets(s, MAX_LINE_LENGTH, stdin);
    clean_head(s);
  }
  if (!strcmp(s, "q"))
    return 1;
  return 0;
}

print_message(m)
     int m;
{
  int i;
  printf("Message #%d (%d lines)\n", m, numlines[m]);
  printf("%s\n", telhead[m]);
  for (i = 0; i < numlines[m]; ++i)
    printf("%s", body[m][i]);
  head[m].status = ' ';
}

#define NEW_STATUS undelete?((head[m].status == 'D')?'U':head[m].status):'D'

process_delete(s,n,undelete)
     char *s;
     int n;
     int undelete;
{
  char *sp = s;
  int m, p, q;
 
  if (!sp || !*sp)
    return;
  while (*sp && *sp == ' ') ++sp;
  s = sp;
  while(*sp && *sp != ' ') ++sp;
  if (*sp)
    process_delete(sp,n,undelete);
  *sp = '\0';
  if (sscanf(s, "%d-%d", &p, &q) == 2)
    if (p > q || p < 1 || q > n)
      printf("Bad range: %d-%d\n", p, q);
    else
      for (m = p; m <= q; ++m)
	head[m].status = NEW_STATUS;
  else if (sscanf(s, "%d", &m) == 1)
    if (m < 1 || m > n)
      printf("Bad message number: %d\n", m);
    else
      head[m].status = NEW_STATUS;
  else if (!strcmp(s, "b")) {
    for (m = 0; m <= n; ++m)
      if (head[m].type == BULL)
	head[m].status = NEW_STATUS;
  }
  else if (!strcmp(s, "p")) {
    for (m = 0; m <= n; ++m)
      if (head[m].type == PROD)
	head[m].status = NEW_STATUS;
  }
  else if (!strcmp(s, "*")) {
    for (m = 0; m <= n; ++m)
      head[m].status = NEW_STATUS;
  }
}

mail_help()
{
  puts("Commands are:");
  puts("h                     print the list of headers");
  puts("<n>                   print message number <n>");
  puts("d <message list>      delete message list");
  puts("u <message list>      undelete message list");
  puts("q                     quit and save changes");
  puts("x                     quit without saving changes");
  puts("");
  puts("For delete and undelete, if no <message list> is specified, then the");
  puts("current message is used.  Other choices for <message list> are:");
  puts("  <n>                 message number <n>");
  puts("  <n>-<m>             messages <n> through <m>");
  puts("  <n1> <n2> ... <nm>  messages <n1>, <n2>, ..., and <nm>");
  puts("  p                   all Production Reports");
  puts("  b                   all BULLETINS");
  puts("  *                   all messages");
  puts("");
  puts("The meanings of the message markers are:");
  puts("  N                   new");
  puts("  U                   unread");
  puts("  R                   read");
  puts("  D                   deleted");
}

