/****************************************/
/* ML-Support                           */
/* Freeware                             */
/* © 1998-2000 Christian Hattemer       */
/* email: chris@riednet.tu-darmstadt.de */
/* 23.08.2000 18:21                     */
/****************************************/

/* stormamiga.lib */
#ifdef USESTORMAMIGA
   #define STORMAMIGA
   #include <stormamiga.h>
   #define snprintf snprintf_
#endif

/* Protos */
#include <proto/intuition.h>
#include <proto/rexxsyslib.h>

#include <rexx/errors.h>

/* Ansi */
#include <stdio.h>
#include <string.h>

#include "YAM.h"

/* ML-Support Includes */
#include "/Creator.h"
#include "/Mainwin.h"
#include "/MLList.h"

/* Functions */
METHOD YAM_New    (Class *cl, Object *obj, struct opSet *msg);
METHOD YAM_Dispose(Class *cl, Object *obj, Msg msg);
METHOD YAM_Create (Class *cl, Object *obj, struct MUIP_YAM_Create *msg);
ULONG SAVEDS YAM_Dispatcher (REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) Msg msg);

static LONG SendRexxCommand(STRPTR Port, STRPTR Cmd, struct MsgPort *ReplyPort, STRPTR Result, size_t Len);

/* Structures */
static struct MUIP_YAM_Create
{
   ULONG  MethodID;
   Object *App;
   Object *WI_Main;
   Object *LV_MLNames;
   Object *CY_Command;
   Object *STR_Custom;
};

METHOD YAM_New(Class *cl, Object *obj, struct opSet *msg)
{
   struct YAM_Data *Data;

   if (!(obj = (Object *)DoSuperMethodA(cl, obj, (Msg)msg)))
   {
      return NULL;
   }

   Data = INST_DATA(cl, obj);

   // Init ARexx Port
   if ((Data->ReplyPort = CreateMsgPort()) == NULL)
   {
      CoerceMethod(cl, obj, OM_DISPOSE);
      return NULL;
   }

   return (ULONG)obj;
}

METHOD YAM_Dispose(Class *cl, Object *obj, Msg msg)
{
   struct YAM_Data *Data = INST_DATA(cl, obj);

   if (Data->ReplyPort)
   {
      DeleteMsgPort(Data->ReplyPort);
   }

   return DoSuperMethodA(cl, obj, msg);
}

METHOD YAM_Create(Class *cl, Object *obj, struct MUIP_YAM_Create *msg)
{
   TEXT   Result[300], StrSubj[180], StrSubj2[195], StrTo[160], StrUserEmail[100];
   STRPTR pStart, pStrEnd, pStrUserRealname;
   LONG   CycleActive, Len, ListEntry = MUIV_List_NextSelected_Start;
   FILE  *Tempfile;

   struct MLListNode *MLN;
   struct YAM_Data *Data = INST_DATA(cl, obj);

   SendRexxCommand("YAM", "USERINFO", Data->ReplyPort, Result, sizeof(Result));

   if (EMPTYSTR(Result) || !strchr(Result, '@'))
   {
      MUI_RequestA(msg->App, msg->WI_Main, 0,
                   "ML-Support",
                   "*_Ok",
                   "YAM is not running,\n"\
                   "or misconfigured.",
                   NULL
                  );
      return 0;
   }

   set(msg->WI_Main, MUIA_Window_Sleep, TRUE);

   // Get User Email

   pStart = strchr(Result, '@');
   while (pStart[0] != ' ')
   {
      pStart--;
   }

   Len = 1;
   while (pStart[Len] != ' ')
   {
      Len++;
   }
   pStart[Len] = '\0';
   stccpy(StrUserEmail, pStart, sizeof(StrUserEmail));
   pStart[Len] = ' ';

   // Get User Realname

   pStart += Len;

   pStrEnd = strchr(pStart, ':');
   while (pStrEnd[0] != ' ')
   {
      pStrEnd--;
   }

   pStrEnd[0] = '\0';
   pStrUserRealname = pStart;

   // which Mode?
   CycleActive = xget(msg->CY_Command, MUIA_Cycle_Active);

   for (;;)
   {
      DoMethod(msg->LV_MLNames, MUIM_List_NextSelected, &ListEntry);
      if (ListEntry == MUIV_List_NextSelected_End)
      {
         break;
      }

      DoMethod(msg->LV_MLNames, MUIM_List_GetEntry,
               ListEntry, &MLN
              );

      // Don't create a subscription mail if the ML is already
      // subscribed or vice versa

      if ((CycleActive == 0 && MLN->IsSubs == TRUE) ||
          (CycleActive == 1 && MLN->IsSubs == FALSE)
         )
      {
         continue;
      }

      // Create To: String

      if (MLN->ToCmd)
      {
         switch (CycleActive)
         {
            case 0:
               snprintf(StrTo, sizeof(StrTo), "WRITETO %s%s", MLN->SubsCmd, MLN->ServerAdd);
               break;

            case 1:
               snprintf(StrTo, sizeof(StrTo), "WRITETO %s%s", MLN->UnsubsCmd, MLN->ServerAdd);
               break;

            case CY_COMMAND_ENTRY_CUSTOM:
               MUI_Request(msg->App, msg->WI_Main, 0,
                           "ML-Support",
                           "*_Ok",
                           "%s:\n"\
                           "Sorry, this mode does not work with the\n"\
                           "'Cmd in To:' mode which you have set in\n"\
                           "the Editwindow.",
                           MLN->MLName
                          );
               continue;
               break;
         }
      }
      else
      {
         snprintf(StrTo, sizeof(StrTo), "WRITETO %s", MLN->ServerAdd);
      }

      // Create Subject: String

      switch (CycleActive)
      {
         case 0:
            stccpy(StrSubj, MLN->SubsCmd, sizeof(StrSubj));
            if (MLN->IsSubs == FALSE)
            {
               MLN->IsSubs = TRUE;
               set(msg->LV_MLNames, MUIA_MLList_Changed, TRUE);
            }
            break;

         case 1:
            stccpy(StrSubj, MLN->UnsubsCmd, sizeof(StrSubj));
            if (MLN->IsSubs == TRUE)
            {
               MLN->IsSubs = FALSE;
               set(msg->LV_MLNames, MUIA_MLList_Changed, TRUE);
            }
            break;

         case CY_COMMAND_ENTRY_CUSTOM:
            stccpy(StrSubj, (STRPTR)xget(msg->STR_Custom, MUIA_String_Contents), sizeof(StrSubj));
            break;
      }

      if (CycleActive != CY_COMMAND_ENTRY_CUSTOM)
      {
         switch (MLN->AddData)
         {
            case 0:
               break;

            case 1:
               strncat(StrSubj, StrUserEmail, sizeof(StrSubj)-strlen(StrSubj));
               break;

            case 2:
               if (CycleActive != 1)
               {
                  strncat(StrSubj, pStrUserRealname, sizeof(StrSubj)-strlen(StrSubj));
               }
               break;

            case 3:
               strncat(StrSubj, StrUserEmail, sizeof(StrSubj)-strlen(StrSubj));
               if (CycleActive != 1)
               {
                  strncat(StrSubj, pStrUserRealname, sizeof(StrSubj)-strlen(StrSubj));
               }
               break;

            case 4:
               if (CycleActive != 1)
               {
                  strncat(StrSubj, pStrUserRealname, sizeof(StrSubj)-strlen(StrSubj));
               }
               strncat(StrSubj, StrUserEmail, sizeof(StrSubj)-strlen(StrSubj));
               break;
         }
      }

      if (Tempfile = fopen("T:MLS-Temp", "w"))
      {
         fputs(StrSubj, Tempfile);
         fclose(Tempfile);
      }

      snprintf(StrSubj2, sizeof(StrSubj2), "WRITESUBJECT \"%s\"", StrSubj);

      SendRexxCommand("YAM", "MAILWRITE QUIET" , Data->ReplyPort, Result, sizeof(Result));
      SendRexxCommand("YAM", StrTo       , Data->ReplyPort, Result, sizeof(Result));
      SendRexxCommand("YAM", StrSubj2    , Data->ReplyPort, Result, sizeof(Result));
      SendRexxCommand("YAM", "WRITELETTER T:MLS-Temp NOSIG", Data->ReplyPort, Result, sizeof(Result));
      SendRexxCommand("YAM", "WRITEQUEUE", Data->ReplyPort, Result, sizeof(Result));
   }

   if (CycleActive != CY_COMMAND_ENTRY_CUSTOM)
   {
      DoMethod(msg->LV_MLNames, MUIM_List_Redraw, MUIV_List_Redraw_All);
      DoMethod(msg->WI_Main, MUIM_Mainwin_CYCmdState);
   }

   set(msg->WI_Main, MUIA_Window_Sleep, FALSE);

   return 0;
}

ULONG SAVEDS YAM_Dispatcher(REG(a0) Class *cl, REG(a2) Object *obj, REG(a1) Msg msg)
{
   switch (msg->MethodID)
   {
      case OM_NEW             : return YAM_New    (cl, obj, (APTR)msg);
      case OM_DISPOSE         : return YAM_Dispose(cl, obj, (APTR)msg);
      case MUIM_Creator_Create: return YAM_Create (cl, obj, (APTR)msg);
   }

   return DoSuperMethodA(cl, obj, msg);
}

static LONG SendRexxCommand(STRPTR Port, STRPTR Cmd, struct MsgPort *ReplyPort, STRPTR Result, size_t Len)
{
   struct MsgPort *RexxPort;

   *Result = '\0';

   Forbid();

   if (RexxPort = FindPort(Port))
   {
      struct RexxMsg *rexxMsg, *Answer;

      if (rexxMsg = CreateRexxMsg(ReplyPort, NULL, NULL))
      {
         if (rexxMsg->rm_Args[0] = CreateArgstring(Cmd, strlen(Cmd)))
         {
            LONG Status;

            rexxMsg->rm_Action = RXCOMM | RXFF_RESULT;

            PutMsg(RexxPort, &rexxMsg->rm_Node);

            Permit();

            do
            {
               WaitPort(ReplyPort);
               Answer = (struct RexxMsg *)GetMsg(ReplyPort);
            } while (Answer == NULL);

            Status = Answer->rm_Result1;
            if (Status == RC_OK)
            {
               if (Answer->rm_Result2)
               {
                  stccpy(Result, (STRPTR)Answer->rm_Result2, Len);
                  DeleteArgstring((UBYTE *)Answer->rm_Result2);
               }
            }

            DeleteArgstring((UBYTE *)ARG0(Answer));
            DeleteRexxMsg(Answer);

            return Status;
         }
         else
         {
            DeleteRexxMsg(rexxMsg);
         }
      }
   }

   Permit();

   return RC_FATAL;
}

