#include "prefs.h"

#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <intuition/intuition.h>

#ifdef LATTICE
#include <proto/exec.h>
#include <proto/dos.h>
#include <proto/reqtools.h>
#endif
#include <libraries/reqtools.h>
#include <time.h>



Prototype void CreateHeader(FILE*,char*,char*);
Prototype BOOL SetFolderName(char *);
Prototype FILE *OpenHomeBox(void);
Prototype void CloseHomeBox(FILE *);
Prototype char *plural_s(int);
Prototype int plural_pix(int);
Prototype int send_off(char *,char *);
Prototype void append_sig(FILE *);
Prototype void append_elmheader(FILE *);
Prototype void set_options(void);
Prototype void outline(void);
Prototype void OpenTTY(void);
Prototype void Usage(void);
Prototype void DirectSend(char *,char *);
Prototype void copy_and_do_alias(FILE *,FILE *);
Prototype void copy_and_do_from(FILE *,FILE *);
Prototype void str_replace(char *,char *,char *);
Prototype void do_introduction(FILE *,char *,struct MailItem *);
Prototype void clean_exit(int);
Prototype void status_msg(char *, long);
Prototype char *parse_arpa_from(char *);
Prototype char lastch(char *);



char lastch(char *str)
{
  int len;
  len = strlen(str);
  if (str && len)
    return(str[len-1]);
  else
    return('\0');
}



void
CreateHeader(FILE* fp,char* To, char* Subject)
{
  fprintf(fp,"To: %s\n",STR(To));
  fprintf(fp,"Subject: %s\n",STR(Subject));
}



BOOL
SetFolderName(char *file)
{
  char *foldername;
  FILE *fp;

  if (file && strlen(file) && (foldername=strdup(file))) {
    /* IMHO it's not neccessary to lock the folder here */
    if (fp=fopen(foldername,"r")) {
      fclose(fp);
      if (FolderName) free(FolderName);
      FolderName = foldername;
      return(TRUE);
    }
    free(foldername);
  }

  return(FALSE);
}



FILE *OpenHomeBox(void)
{
  LockFile(FolderName);
  return(fopen(FolderName,"r"));
}



void CloseHomeBox(FILE *folder)
{
  fclose(folder);
  UnLockFile(FolderName);
}



/* send_off schickt die Mail in file ab, wenn die Abfrage mit 'S' */
/* beantwortet wurde. Der Returnwert ist 1, wenn die Mail versandt */
/* 2, wenn noch mals editiert werden soll und 0 wenn abgebrochen werden */
/* soll */

int send_off(char *file,char *in_reply_to)
{
  FILE *in,*out;
  char c;
  char String[MAX_LINELENGTH];
  char *tfile;
  BOOL display_header = TRUE;

  /* complete header - begin */

  if (tfile=malloc(strlen(file)+3)) {         /* len + ".o" + null */
    strcpy(tfile,file);
    strcat(tfile,".o");
    remove(tfile);
    rename(file,tfile);
    remove(file);
    if (out=fopen(file,"w")) {
      if (SendmailVersion==SM_FEULNER)
        fprintf(out,"From: %s@%s%s (%s)\n",UserName,HostName,DomainName,RealName);
      if (in_reply_to)
        fprintf(out,"In-Reply-To: %s\n",in_reply_to);
      if (WantReturn)
        fprintf(out,"Return-Receipt-To: %s@%s%s\n",UserName,HostName,DomainName);
      append_elmheader(out);
      if (in=fopen(tfile,"r")) {
        copy_and_do_alias(in,out);
        copy_and_do_from(in,out);
        fclose(in);
      }
      fclose(out);
      remove(tfile);
    }
  }

  /* complete header - end */

  while (TRUE) {

    if (display_header) {
      sprintf(TBuffer,"\033[%d;1H\033[J",Win_Height-1);
      outline();
      putst("And now: \n");
      putst_center("Choose e)dit message, s)end, S)end without signature, or f)orget.");
      sprintf(TBuffer,"\033[%d;10H",Win_Height-1);
      outline();
      display_header = FALSE;
    }

    flush_input();

    c=getch();
    if (toupper(c)=='S') {
      putst("Send");

      if (c=='s') {
        if (out=fopen(file,"a")) {
          append_sig(out);
          fclose(out);
        }
      }
      else
        putst(" (without signature)");

      if (in=fopen(file,"r")) {
        if (SentArchive) {
          if (out=fopen(SentArchive,"a")) {
            long t;
            time(&t);
            fprintf(out,"From %s (ARCHIVE)\n",UserName);
            fprintf(out,"Date: %s",ctime(&t));
            if (SendmailVersion!=SM_FEULNER)
              fprintf(out,"From: %s@%s%s (%s)\n",UserName,HostName,DomainName,RealName);
            copy_and_do_from(in,out);
            fclose(out);
          }
        }
        fclose(in);
      }

      if (SendmailVersion==SM_FEULNER)
        sprintf(String,"sendmail <%s",file);
      else if (SendmailVersion==SM_DILLON)
        sprintf(String,"sendmail <%s -f %s -R \"%s\"",file,UserName,RealName);
      else if (SendmailVersion==SM_OTHER)
        sprintf(String,"sendmail <%s -f %s",file,UserName);

      Execute(String,0L,0L);
      return 1;
    }
    else if (c=='e') {
      putst("Edit message");
      editfile(file);
      display_header = TRUE;
    }
    else if (c=='f') {
      putst("Forget");
      return 0;
    }
  }
}



void
copy_and_expand_alias(FILE *in, FILE *out, long start, long end)
{
  char *buf,*ptr;
  BOOL erstes = TRUE;
  struct AliasItem *list,*l,*inner,*i;

  if (buf = malloc(end-start+2)) {
    fseek(in,start,0);
    fread(buf,1,end-start+1,in);
    buf[end-start+1] = '\0';

    ptr = strchr(buf,':');
    *ptr = '\0';
    ptr++;

    l = list = AdrsToAList(ptr);

    if (list)
      fprintf(out,"%s: ",buf);

    while (l) {
      /*printf("mal sehen: %s -> %s -> %s\n",l->alias,l->real,GetAlias(AliasList,l->alias));*/
      i = inner = AdrsToAList(l->real?l->real:l->alias);
      while (i) {
        fprintf(out,"%s%s",erstes?"":",\n\t",i->real?i->real:i->alias);
        erstes = FALSE;
        i = i->next;
      }
      FreeAliasList(&inner);
      l = l->next;
    }

    if (list)
      fputc('\n',out);

    FreeAliasList(&list);

    if (erstes)
      fprintf(stderr,"To: line is empty\n");

    free(buf);
  }
}



void
copy_and_do_alias(FILE *in,FILE *out)
{
  char buf[MAX_LINELENGTH];
  long pos,start,end;

  buf[MAX_LINELENGTH-1]='\0';   /* 100% null-terminated */

  while(getline(in,buf,&pos)) {
    if (!strlen(buf)) {   /* end of header, message body begins */
      fputc('\n',out);
      return;
    }
    else if (!strnicmp(buf,"To:",3) || !strnicmp(buf,"Cc:",3) || !strnicmp(buf,"Bcc:",4)) {
      start = pos;
      while(getline(in,buf,&pos) && (*buf==' ' || *buf=='\t'))
        ;
      end = pos-1;
      copy_and_expand_alias(in,out,start,end);
    }
    else
      fprintf(out,"%s\n",buf);
  }
}



void
copy_and_do_from(FILE *in,FILE *out)
{
  char buf[MAX_LINELENGTH];
  buf[MAX_LINELENGTH-1]='\0';   /* 100% null-terminated */
  while(fgets(buf,MAX_LINELENGTH-1,in)) {
    if (strncmp("From ",buf,5)==0)
      fprintf(out,">%s",buf);
    else
      fputs(buf,out);
  }
}



void
append_elmheader(FILE *file)
{
  FILE *in;
  char *headerfile;

  if (headerfile = malloc(strlen(UULIB)+strlen(UserName)+strlen(ELM_HEADERS)+1)) {

    strcpy(headerfile,UULIB);
    strcat(headerfile,UserName);
    strcat(headerfile,ELM_HEADERS);

    if (!(in=fopen(headerfile,"r"))) {
      strcpy(headerfile,UULIB);
      strcat(headerfile,ELM_HEADERS);
      in=fopen(headerfile,"r");
    }

    fprintf(file,"X-Mailer: //\\\\miga Electronic Mail (AmiElm %s)\n",VERSION);

    if (in) {
      char line[MAX_LINELENGTH];
      line[MAX_LINELENGTH-1]='\0';
      while(fgets(line,MAX_LINELENGTH-1,in))
        if (strlen(line) && strchr(line,':'))
          fputs(line,file);
      fclose(in);
    }

    free(headerfile);
  }
}



void
append_sig(FILE *file)
{
  FILE *in;
  char *sigfile;

  if (sigfile = malloc(strlen(UULIB)+strlen(UserName)+strlen(SIGNATURE)+1)) {

    strcpy(sigfile,UULIB);
    strcat(sigfile,UserName);
    strcat(sigfile,SIGNATURE);

    if (!(in=fopen(sigfile,"r"))) {
      strcpy(sigfile,UULIB);
      strcat(sigfile,SIGNATURE);
      in=fopen(sigfile,"r");
    }

    if (in) {
      register int c;
      while((c=getc(in))!=EOF)
        putc(c,file);
      fclose(in);
    }

    free(sigfile);
  }
}



void
set_options(void)
{
  char c;
  BOOL Quit = FALSE;

  while(!Quit) {
    putst("\f \n\n");   /* extra space for character mapped console windows */
    putst_center_bold("O p t i o n s");
    putch('\n');
    putst_center_bold("_______________");
    putst("\033[8;1HWhich option do you want to change (toggle) ?\n");
    putst(" (caution, changes are temporary!)\n\n\n");

    putst("   (1)  Handle Return-Receipt-To     (");
    if (ReturnReceipt)
      putst("on)\n");
    else
      putst("off)\n");

    putst("   (2)  Handle Return-\033[1mView\033[m-To        (");
    if (ReturnView)
      putst("on)\n");
    else
      putst("off)\n");

    putst("   (3)  Request Return-Receipt-To    (");
    if (WantReturn)
      putst("on)\n");
    else
      putst("off)\n");

    putst("   (4)  Request Return-\033[1mView\033[m-To       (");
    if (WantReturn)
      putst("on)\n");
    else
      putst("off)\n");

    putst("   (5)  Show full header             (");
    if (ShowHeader)
      putst("on)\n");
    else
      putst("off)\n");

    putst("   (6)  Show signatures              (");
    if (ShowSig)
      putst("on)\n");
    else
      putst("off)\n");

    putst("   (7)  Keep backups                 (");
    if (KeepBackup)
      putst("on)\n");
    else
      putst("off)\n");

    putst("\n\n\n");
    putst_center(" Choose 1-7, or any other key to return: ");
    flush_input();
    c=getch();
    switch (c) {
      case '1': ReturnReceipt = !ReturnReceipt; break;
      case '2': ReturnView    = !ReturnView;    break;
      case '3': WantReturn    = !WantReturn;    break;
      case '4': WantView      = !WantView;      break;
      case '5': ShowHeader    = !ShowHeader;    break;
      case '6': ShowSig       = !ShowSig;       break;
      case '7': KeepBackup    = !KeepBackup;    break;
      default : Quit          = TRUE;           break;
    }
  }
}



/* Lowlevelroutinen zur Behandlung eines RAW-Fensters. Damit wird die
 * Eingabepufferung der Standard-C Routinen umgangen; ausserdem koennen
 * so die Cursortasten vom Programm aus abgefragt werden
 */

void
OpenTTY(void)
{
    if (!open_intuition()) {
      fprintf(stderr,"elm: cannot open tty\n");
      clean_exit(103);
    }
}



void
outline(void)
{
  putst(TBuffer);
}



/* Die naechste Prozedur gibt eine kleine Bedienungsanleitung auf dem
 * Bildschirm aus und verlaesst das Programm dann
 */
void
Usage(void)
{
    printf("\033[1;33mAmiga Elm \033[0m%s © 1991-1992 Andreas M. Kirchwitz (amk@zikzak.in-berlin.de)\n",VERSION);
    printf("(based on hwr-mail by Heiko W. Rupp, hwr@pilhuhn.ka.sub.org)\n");
    printf("Usage: elm \033[3m[?|-v|-h|-?|-f] [<user>] [-s <subject>]\033[0m\n");
    clean_exit(0);
}



void
DirectSend(char *To,char *Subject)
{
    OpenTTY();
    sendmail(To,Subject);
    clean_exit(0);
}



char *
plural_s(int number)
{
  return( (number==1)?"":"s" );
}



int
plural_pix(int number)
{
  return( (number==1)?1:0 );
}



void
str_replace(char *workbuf, char *search, char *replace)
{
  char *p;

  if (replace && strlen(replace) && (p=strstr(workbuf,search))) {
    char *s = p+strlen(search);
    char *d = p;

    while (*d++=*s++)
      ;

    strins(p,replace);
  }
}



void do_introduction(FILE *out, char *intro, struct MailItem *I)
{
  int nnum;
  char *str;
  char *fname = NULL;

  if (intro && strlen(intro)) {
    if (I->FromName) {
      fname=malloc(strlen(I->FromName)+1);
      for(nnum=0;I->FromName[nnum]!='\0' && I->FromName[nnum]!=' ';nnum++)
        fname[nnum]=I->FromName[nnum];
      fname[nnum]='\0';
    }

    if (str=malloc(strlen(intro)+2*strlen(I->From)+strlen(I->MessageID)+strlen(I->Date)+1)) {
      strcpy(str,intro);
      str_replace(str,"$FIRSTNAME",fname);
      if (I->FromName && strlen(I->FromName))
        str_replace(str,"$NAME",I->FromName);
      else
        str_replace(str,"$NAME",I->From);
      str_replace(str,"$MSGID",I->MessageID);
      str_replace(str,"$DATE",I->Date);
      fprintf(out,"%s\n\n",str);
    }
  }
}



void clean_exit(int err_code)
{
  struct MailItem *del;
  close_intuition();
  if (MailTmp) remove(MailTmp);
  UnLockFiles();
  while(MailList) {
    del = MailList;
    MailList = MailList->next;
    free(del);
  }
  FreeAliasList(&AliasList);
  CloseReqToolsLib();
  /*
     aus unerfindlichen Gruenden produziert exit() Enforcer-Hits, wenn man
     Elm startet, ein Reply macht, dies jedoch dann mit f)orget abbricht
     und dann das Programm beendet
  */
  exit(err_code);
}



void status_msg(char *msg, long delay_time)
{
  int hpos;
  if (intui_interface()) {
    hpos = (Win_Width-strlen(msg))/2;
    if (hpos<0)
      hpos=0;
    sprintf(TBuffer,"\033[%d;1H\033[J\033[%d;%dH[%.*s]",Win_Height,Win_Height,hpos-1,Win_Width-2,msg);
    outline();
    if (delay_time>0L)
      Delay(delay_time);
  }
  else
    fprintf(stderr,"elm: %s\n",msg);
}



char *parse_arpa_from(char *str)
{
  /** try to parse the 'From:' line given... It can be in one of
      two formats:
            From: Dave Taylor <hpcnou!dat>
        or  From: hpcnou!dat (Dave Taylor)
      Change 'newfrom' ONLY if sucessfully parsed this entry and
      the resulting name is non-null!
  **/

  char *temp_buffer, *temp, *ret=NULL, *buffer;
  register int i, j = 0, in_parens;

  if (!(buffer=strdup(str)))
    return(NULL);

  removeCR(buffer);    /* blow away '\n' char! */
  buffer = delete_wspaces_begin(buffer);
  delete_wspaces_end(buffer);

  if (!(temp_buffer=malloc(strlen(buffer)+1))) {
    free(buffer);
    return(NULL);
  }

  temp = temp_buffer;
  *temp = '\0';

  if (lastch(buffer) == '>') {
/*
    for (i=0; buffer[i] != '\0' && buffer[i] != '<' &&
         buffer[i] != '('; i++)
*/
    for (i=0; buffer[i] != '\0' && buffer[i] != '<'; i++)
      temp[j++] = buffer[i];
    temp[j] = '\0';
  }
  else if (lastch(buffer) == ')') {
    in_parens = 1;
    for (i=strlen(buffer)-2; i>=0 && buffer[i] != '\0' && buffer[i] != '<'; i--) {
      switch(buffer[i]) {
        case ')':  in_parens++;
                   break;
        case '(':  in_parens--;
                   break;
      }
      if(!in_parens) break;
      temp[j++] = buffer[i];
    }
    temp[j] = '\0';
    strrev(temp);
  }

/*
  /* We want a REAL name... else NULL... */

  temp = delete_wspaces_begin(temp);
  delete_wspaces_end(temp);

  /** if we have a null string at this point, we must just have a
      From: line that contains an address only.  At this point we
      can have one of a few possibilities...

    From: address
    From: <address>
    From: address ()
  **/

  j = 0;

  if (strlen(temp) == 0) {
    if (lastch(buffer) != '>') {
      for (i=0; buffer[i] != '\0' && buffer[i] != '('; i++)
        temp[j++] = buffer[i];
      temp[j] = '\0';
    }
    else {  /* get outta '<>' pair, please! */
      for (i=strlen(buffer)-2;buffer[i] != '<' && buffer[i] != ':' && i>=0;i--)
        temp[j++] = buffer[i];
      temp[j] = '\0';
      strrev(temp);
    }
  }
*/

  temp = delete_wspaces_begin(temp);
  delete_wspaces_end(temp);

  if (strlen(temp) > 0) {    /* mess with buffer... */

    i = strlen(temp) - 1;

    /* remove surrounding paired quotation marks */
    if((temp[i] == '"') & (temp[0] == '"')) {
      temp[i] = '\0';
      temp++;
    }

    /* if anything is left, let's change 'from' value! */

    if (strlen(temp) > 0)
      ret = strdup(temp);
  }

  free(buffer);
  free(temp_buffer);

  return(ret);
}

