#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/rexxsyslib_protos.h>
#include <rexx/errors.h>

#include "include/Messiecommon.h"
#include "include/Messierexxport.h"

extern struct RxsLib *RexxSysBase;

UBYTE MessieRexxPort::rexxportname[]="AREXX";
char MessieRexxPort::portname[]="MESSIE";

// DO NOT CHANGE THE PATTERN!!!
char MessieRexxPort::argtemplate[]="START/S,STOP/S,CHANNEL=CH/K/N,INTERVAL=INT/K/N,"
                                    "COMMENT=COM/K,LOCKGUI/S,UNLOCKGUI/S,QUIT/S";

MessieRexxPort::MessieRexxPort(void) {
  error=1;
  myrexxport=0;
  args=0;
  
  if((RexxSysBase))
   myrexxport=CreateMsgPort();
  else 
   PrintString("No rexxsyslib.library.\n");
  
  if((myrexxport)) {
    myrexxport->mp_Node.ln_Name=portname;
    AddPort(myrexxport);
    signals=(1L<<myrexxport->mp_SigBit);
   } else {
    PrintString("No AREXX port.\n");
   }
  
  args=(struct RDArgs *)AllocDosObject(DOS_RDARGS,0);

  if(args != 0) 
   error=0;
  else
   PrintString("No ReadArgs.\n");
  
}

MessieRexxPort::~MessieRexxPort() {
  if(args != 0) FreeDosObject(DOS_RDARGS,args);

  if((myrexxport)) {
    RemPort(myrexxport);
    DeleteMsgPort(myrexxport);
   }
}

void MessieRexxPort::CheckPort(void) {

  if(error != 0) return;
  
   while((msg=GetMsg(myrexxport)))
    {
     if((IsRexxMsg((RexxMsg *)msg))) {
       char * txt=(char *)(((RexxMsg *)msg)->rm_Args[0]);
       LONG res1=0,res2=0;
       if(((RexxMsg *)msg)->rm_Action & RXCOMM == 0) {
         // Function calls enden hier. Wie behandelt man Irrläufer?
         ((RexxMsg *)msg)->rm_PassPort=FindPort(rexxportname);
       } else {

/* Let's try to be C= BUG-compatible */

         if(txt[strlen(txt)-1] != '\n') {
          if(strlen(txt)+1 > 200) PrintString("Sorry, string too long. Please report.\n");
          else {
          strcpy(buf,txt);
          txt=buf;
          char *tmp=txt+strlen(txt);
          tmp[0]='\n';
          tmp[1]='\0';
          }
         } 

/* should be good enough */
                 
         for(int i=0;i<=7; i++) {
          argbufs[i]=0;
         }

        args->RDA_Source.CS_Buffer=(UBYTE *)txt;
        args->RDA_Source.CS_Length=strlen(txt)+1;
        args->RDA_Source.CS_CurChr=0;        
        args->RDA_DAList=0;
        args->RDA_Buffer=0;
        args->RDA_BufSiz=0;
        args->RDA_ExtHelp=0;
        args->RDA_Flags=RDAF_NOPROMPT;
        bool cmdok=false;

        if(ReadArgs(argtemplate,argbufs,args)!=0) {
         // filter senseless combinations
         int opts=0;

         for(int i=0;i<=7;i++) {
          if(argbufs[i] != 0) opts++;
         }
         
         if(argbufs[2]!=0) opts-=1; //number of selected options, ch is no opt
         
         if(opts == 1) {  //allow only one option a time
         
          cmdok=true;
           
          if(argbufs[2] == 0) { //means no channel, not channel 0
           if(argbufs[5]!=0) LockGUI(true);
           else if(argbufs[6]!=0) LockGUI(false);
           else if(argbufs[0]!=0) Start();
           else if(argbufs[1]!=0) Stop();
           else if(argbufs[7]!=0) SetSignal(SIGBREAKF_CTRL_C,SIGBREAKF_CTRL_C); // Quit
           else cmdok=false; // hm... would have required a channel (int,com)

          } else {  // ch set
           
          int *pch=(int *)argbufs[2];
          if((*pch < 0) || (*pch >= MAXCHANNELS)) {
           cmdok=false;
           PrintString("Invalid channel.\n");
          } else { // channel is valid
            if(argbufs[0]!=0) Start(*pch);
            else if(argbufs[1]!=0) Stop(*pch);
            else if(argbufs[3]!=0) {
             int *pint=(int *)argbufs[3];
             if(*pint <= 0) {cmdok=false;PrintString("Invalid interval.\n");}
              else SetInterval(*pch,*pint);
            } else if(argbufs[4]!=0) {
              if(strlen((char *)argbufs[4]) <80) SaveComment((char *)argbufs[4],*pch);
              else PrintString("Comment too long.\n");
             }
            else cmdok=false; 
           }
          }
         } // if one command
        } else PrintString("Error parsing command line.\n");
        FreeArgs(args);

        if(cmdok==false) {
         ((RexxMsg *)msg)->rm_PassPort=FindPort(rexxportname);
         res1=RC_ERROR;
         res2=ERR10_001;
        }
       }
       ((RexxMsg *)msg)->rm_Result1=res1;
       ((RexxMsg *)msg)->rm_Result2=res2;
     } else  PrintString("unknown message type\n");
         
      if(msg) ReplyMsg(msg);
    }
}

long int MessieRexxPort::GetSignalMask(void) {
  return((1L<<myrexxport->mp_SigBit));
 }


