/* Unfortunately Amiga specific because of pattern parsing in SelectField() */

#include "billingkom.h"

#include <dos/dos.h>
#include <clib/dos_protos.h>

#ifdef __SASC
extern struct DOSBase *DOSBase;
#include <pragmas/dos_pragmas.h>
#endif

struct selectflag
{
   char *name;
   unsigned long type;
   unsigned long flag;
};

struct selectfield
{
   char *name;
   bool indexed;
   unsigned long code;
};

#define TYPE_GLOBAL  1
#define TYPE_USER    2

struct selectflag selectflags[] = { { "Archive"      , TYPE_USER    , UMSUSTATF_Archive     },
                                  { "Junk"         , TYPE_USER    , UMSUSTATF_Junk        },
                                  { "PostPoned"    , TYPE_USER    , UMSUSTATF_PostPoned   },
                                  { "Selected"     , TYPE_USER    , UMSUSTATF_Selected    },
                                  { "Old"          , TYPE_USER    , UMSUSTATF_Old         },
                                  { "WriteAccess"  , TYPE_USER    , UMSUSTATF_WriteAccess },
                                  { "ReadAccess"   , TYPE_USER    , UMSUSTATF_ReadAccess  },
                                  { "ViewAccess"   , TYPE_USER    , UMSUSTATF_ViewAccess  },
                                  { "Owner"        , TYPE_USER    , UMSUSTATF_Owner       },

                                  { "UFlag0"       , TYPE_USER    , (1<<0 )               },
                                  { "UFlag1"       , TYPE_USER    , (1<<1 )               },
                                  { "UFlag2"       , TYPE_USER    , (1<<2 )               },
                                  { "UFlag3"       , TYPE_USER    , (1<<3 )               },
                                  { "UFlag4"       , TYPE_USER    , (1<<4 )               },
                                  { "UFlag5"       , TYPE_USER    , (1<<5 )               },
                                  { "UFlag6"       , TYPE_USER    , (1<<6 )               },
                                  { "UFlag7"       , TYPE_USER    , (1<<7 )               },
                                  { "UFlag8"       , TYPE_USER    , (1<<8 )               },
                                  { "UFlag9"       , TYPE_USER    , (1<<9 )               },
                                  { "UFlagA"       , TYPE_USER    , (1<<10)               },
                                  { "UFlagB"       , TYPE_USER    , (1<<11)               },
                                  { "UFlagC"       , TYPE_USER    , (1<<12)               },
                                  { "UFlagD"       , TYPE_USER    , (1<<13)               },
                                  { "UFlagE"       , TYPE_USER    , (1<<14)               },
                                  { "UFlagF"       , TYPE_USER    , (1<<15)               },

                                  { "Deleted"      , TYPE_GLOBAL  , UMSGSTATF_Deleted     },
                                  { "Expired"      , TYPE_GLOBAL  , UMSGSTATF_Expired     },
                                  { "Exported"     , TYPE_GLOBAL  , UMSGSTATF_Exported    },
                                  { "Orphan"       , TYPE_GLOBAL  , UMSGSTATF_Orphan      },
                                  { "Link"         , TYPE_GLOBAL  , UMSGSTATF_Link        },
                                  { "Hardlink"     , TYPE_GLOBAL  , UMSGSTATF_HardLink    },
                                  { "Parked"       , TYPE_GLOBAL  , UMSGSTATF_Parked      },
                                  { "HasFile"      , TYPE_GLOBAL  , UMSGSTATF_HasFile     },

                                  { NULL,0,0                  } };

/* The indexed fields can be configured in ums.config, but these are probably
   always indexed... */

struct selectfield selectfields[] = { { "MsgText"      , FALSE, UMSCODE_MsgText       },
                                      { "FromName"     , TRUE,  UMSCODE_FromName      },
                                      { "FromAddr"     , FALSE, UMSCODE_FromAddr      },
                                      { "ToName"       , TRUE,  UMSCODE_ToName        },
                                      { "ToAddr"       , FALSE, UMSCODE_ToAddr        },
                                      { "MsgID"        , TRUE,  UMSCODE_MsgID         },
                                      { "CreationDate" , FALSE, UMSCODE_CreationDate  },
                                      { "ReceiveDate"  , FALSE, UMSCODE_ReceiveDate   },
                                      { "ReferID"      , TRUE,  UMSCODE_ReferID       },
                                      { "Group"        , TRUE,  UMSCODE_Group         },
                                      { "Subject"      , TRUE,  UMSCODE_Subject       },
                                      { "Attributes"   , FALSE, UMSCODE_Attributes    },
                                      { "Comments"     , FALSE, UMSCODE_Comments      },
                                      { "Organization" , FALSE, UMSCODE_Organization  },
                                      { "Distribution" , FALSE, UMSCODE_Distribution  },
                                      { "Folder"       , TRUE,  UMSCODE_Folder        },
                                      { "FidoID"       , FALSE, UMSCODE_FidoID        },
                                      { "MausID"       , FALSE, UMSCODE_MausID        },
                                      { "ReplyGroup"   , FALSE, UMSCODE_ReplyGroup    },
                                      { "ReplyName"    , FALSE, UMSCODE_ReplyName     },
                                      { "ReplyAddr"    , FALSE, UMSCODE_ReplyAddr     },
                                      { "LogicalToName", FALSE, UMSCODE_LogicalToName },
                                      { "LogicalToAddr", FALSE, UMSCODE_LogicalToAddr },
                                      { "FileName"     , FALSE, UMSCODE_FileName      },
                                      { "RFCMsgNum"    , FALSE, UMSCODE_RFCMsgNum     },
                                      { "FidoText"     , FALSE, UMSCODE_FidoText      },
                                      { "ErrorText"    , FALSE, UMSCODE_ErrorText     },
                                      { "Newsreader"   , FALSE, UMSCODE_Newsreader    },
                                      { "RFCAttr"      , FALSE, UMSCODE_RfcAttr       },
                                      { "FTNAttr"      , FALSE, UMSCODE_FtnAttr       },
                                      { "ZerAttr"      , FALSE, UMSCODE_ZerAttr       },
                                      { "MausAttr"     , FALSE, UMSCODE_MausAttr      },
                                      { "TempFileName" , FALSE, UMSCODE_TempFileName  },

                                      { NULL           , FALSE, 0                     } };
                                      
void SelectFlagsUnset(struct selectflag *selectflag)
{
   long num;


   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelSet,        0,
                       UMSTAG_SelUnset,      UMSFLAG_SEARCHTEMP,
                       TAG_DONE);

   if(selectflag->type == TYPE_GLOBAL)
   {
      UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                          UMSTAG_SelMask,       selectflag->flag,
                          UMSTAG_SelMatch,      0,
                          UMSTAG_SelSet,        UMSFLAG_SEARCHTEMP,
                          UMSTAG_SelUnset,      0,
                          UMSTAG_SelReadGlobal, TRUE,
                          TAG_DONE);
   }
   else
   {
      UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                          UMSTAG_SelMask,       selectflag->flag,
                          UMSTAG_SelMatch,      0,
                          UMSTAG_SelSet,        UMSFLAG_SEARCHTEMP,
                          UMSTAG_SelUnset,      0,
                          TAG_DONE);
   }

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelReadLocal,  TRUE,
                       UMSTAG_SelMask,       UMSFLAG_MATCHSEARCH | UMSFLAG_SEARCHTEMP,
                       UMSTAG_SelMatch,      UMSFLAG_MATCHSEARCH,
                       UMSTAG_SelSet,        0,
                       UMSTAG_SelUnset,      UMSFLAG_MATCHSEARCH,
                       TAG_DONE);

   num=countselected();

   if(num == 1)
      printf("!%-39.39s --> %ld %s\n",selectflag->name,num,strings[STR_SELECTEDTEXT]);

   else
      printf("!%-39.39s --> %ld %s\n",selectflag->name,num,strings[STR_SELECTEDTEXTS]);
}

void SelectFlagsSet(struct selectflag *selectflag)
{
   long num;

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelSet,        0,
                       UMSTAG_SelUnset,      UMSFLAG_SEARCHTEMP,
                       TAG_DONE);

   if(selectflag->type == TYPE_GLOBAL)
   {
      UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                          UMSTAG_SelMask,       selectflag->flag,
                          UMSTAG_SelMatch,      selectflag->flag,
                          UMSTAG_SelSet,        UMSFLAG_SEARCHTEMP,
                          UMSTAG_SelUnset,      0,
                          UMSTAG_SelReadGlobal, TRUE,
                          TAG_DONE);
   }
   else
   {
      UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                          UMSTAG_SelMask,       selectflag->flag,
                          UMSTAG_SelMatch,      selectflag->flag,
                          UMSTAG_SelSet,        UMSFLAG_SEARCHTEMP,
                          UMSTAG_SelUnset,      0,
                          TAG_DONE);
   }

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelReadLocal,  TRUE,
                       UMSTAG_SelMask,       UMSFLAG_MATCHSEARCH | UMSFLAG_SEARCHTEMP,
                       UMSTAG_SelMatch,      UMSFLAG_MATCHSEARCH,
                       UMSTAG_SelSet,        0,
                       UMSTAG_SelUnset,      UMSFLAG_MATCHSEARCH,
                       TAG_DONE);

   num=countselected();

   if(num == 1)
      printf("%-40.40s --> %ld %s\n",selectflag->name,num,strings[STR_SELECTEDTEXT]);

   else
      printf("%-40.40s --> %ld %s\n",selectflag->name,num,strings[STR_SELECTEDTEXTS]);
}

void SelectField(struct selectfield *selectfield,char *searchstring)
{
   long num,parselen,iswild,total;
   char *parsebuf;

   parselen=2*(1+strlen(searchstring))+2;

   if(!(parsebuf=malloc((size_t)parselen)))
   {
      printf("Out of memory\n");
      return;
   }

   iswild=ParsePatternNoCase(searchstring,parsebuf,parselen);

   if(iswild == -1)
   {
      printf(strings[STR_SELECTINVALIDPATTERN],searchstring);
      free(parsebuf);
      return;
   }

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelSet,        0,
                       UMSTAG_SelUnset,      UMSFLAG_SEARCHTEMP,
                       TAG_DONE);

   total=countselected();

   if(iswild == 0 && selectfield->indexed)
   {
      /* No pattern and an indexed field */

      UMSSelectTags(login,UMSTAG_SelWriteLocal,          TRUE,
                          UMSTAG_SelQuick,               TRUE,
                          UMSTAG_SelSet,                 UMSFLAG_SEARCHTEMP,
                          UMSTAG_SelUnset,               0,
                          UMSTAG_WriteMsgField+selectfield->code,     searchstring,
                          TAG_DONE);
   }
   else if(total)
   {
      long lastnum,res,lastprocent,procent,readnum;
      char *field;
      bool done;

      lastnum=0;
      readnum=0;
      lastprocent=100;

      brk=FALSE;
      done=FALSE;

      while(!brk && !done)
      {
         procent=100*readnum/total;

         if(procent != lastprocent)
         {
            printf("%-40.40s %ld%%\x0d",selectfield->name,procent);
            fflush(stdout);
            lastprocent=procent;
         }

         lastnum=UMSSearchTags(login,UMSTAG_SearchLocal, TRUE,
                                     UMSTAG_SearchLast,  lastnum,
                                     UMSTAG_SearchMask,  UMSFLAG_MATCHSEARCH,
                                     UMSTAG_SearchMatch, UMSFLAG_MATCHSEARCH,
                                     TAG_DONE);

         if(!lastnum)
         {
            done=TRUE;
         }
         else
         {
            res=UMSReadMsgTags(login,UMSTAG_RMsgNum,       lastnum,
                                     UMSTAG_ReadMsgField+selectfield->code, &field,
                                     UMSTAG_RNoUpdate,      TRUE,
                                     TAG_DONE);

            if(!field)
               field="";

            if(res)
            {
               if(MatchPatternNoCase(parsebuf,field))
               {
                  UMSSelectTags(login,UMSTAG_SelMsg,  lastnum,
                                      UMSTAG_SelSet,  UMSFLAG_SEARCHTEMP,
                                      UMSTAG_SelWriteLocal, TRUE,
                                      TAG_DONE);

               }

               UMSFreeMsg(login,lastnum);
            }
         }

         readnum++;
         oscheckbreak();
      }
   }

   free(parsebuf);

   if(brk)
      return;

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelReadLocal,  TRUE,
                       UMSTAG_SelMask,       UMSFLAG_MATCHSEARCH | UMSFLAG_SEARCHTEMP,
                       UMSTAG_SelMatch,      UMSFLAG_MATCHSEARCH,
                       UMSTAG_SelSet,        0,
                       UMSTAG_SelUnset,      UMSFLAG_MATCHSEARCH,
                       TAG_DONE);

   num=countselected();

   if(num == 1)
      printf("%-40.40s --> %ld %s\n",selectfield->name,num,strings[STR_SELECTEDTEXT]);

   else
      printf("%-40.40s --> %ld %s\n",selectfield->name,num,strings[STR_SELECTEDTEXTS]);
}

void SelectAge(unsigned long age)
{
   unsigned long num,secs;

   secs=(oscurrentseconds()/(24*60*60) - age)*(24*60*60);

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                           UMSTAG_SelUnset,      UMSFLAG_SEARCHTEMP,
                           TAG_DONE);

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelDate      , secs-1,
                       UMSTAG_SelSet       , UMSFLAG_SEARCHTEMP,
                       TAG_DONE);

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelReadLocal,  TRUE,
                       UMSTAG_SelMask,       UMSFLAG_MATCHSEARCH | UMSFLAG_SEARCHTEMP,
                       UMSTAG_SelMatch,      UMSFLAG_MATCHSEARCH,
                       UMSTAG_SelSet,        0,
                       UMSTAG_SelUnset,      UMSFLAG_MATCHSEARCH,
                       TAG_DONE);

   num=countselected();

   if(num == 1)
      printf("%-40.40s --> %ld %s\n","Age",num,strings[STR_SELECTEDTEXT]);

   else
      printf("%-40.40s --> %ld %s\n","Age",num,strings[STR_SELECTEDTEXTS]);
}

void SelectParentOwner(void)
{
   long num;

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelSet,        0,
                       UMSTAG_SelUnset,      UMSFLAG_SEARCHTEMP,
                       TAG_DONE);

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelParent,     1,
                       UMSTAG_SelMask,       UMSUSTATF_Owner,
                       UMSTAG_SelMatch,      UMSUSTATF_Owner,
                       UMSTAG_SelSet,        UMSFLAG_SEARCHTEMP,
                       UMSTAG_SelUnset,      0,
                       TAG_DONE);

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelReadLocal,  TRUE,
                       UMSTAG_SelMask,       UMSFLAG_MATCHSEARCH | UMSFLAG_SEARCHTEMP,
                       UMSTAG_SelMatch,      UMSFLAG_MATCHSEARCH,
                       UMSTAG_SelSet,        0,
                       UMSTAG_SelUnset,      UMSFLAG_MATCHSEARCH,
                       TAG_DONE);

   num=countselected();

   if(num == 1)
      printf("%-40.40s --> %ld %s\n","ParentOwner",num,strings[STR_SELECTEDTEXT]);

   else
      printf("%-40.40s --> %ld %s\n","ParentOwner",num,strings[STR_SELECTEDTEXTS]);
}

void SelectLocal(void)
{
   long num;

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelSet,        0,
                       UMSTAG_SelUnset,      UMSFLAG_SEARCHTEMP,
                       TAG_DONE);

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelQuick,      TRUE,
                       UMSTAG_WGroup,        currentgroup,
                       UMSTAG_SelSet,        UMSFLAG_SEARCHTEMP,
                       UMSTAG_SelUnset,      0,
                       UMSTAG_SelReadGlobal, TRUE,
                       TAG_DONE);

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelReadLocal,  TRUE,
                       UMSTAG_SelMask,       UMSFLAG_MATCHSEARCH | UMSFLAG_SEARCHTEMP,
                       UMSTAG_SelMatch,      UMSFLAG_MATCHSEARCH,
                       UMSTAG_SelSet,        0,
                       UMSTAG_SelUnset,      UMSFLAG_MATCHSEARCH,
                       TAG_DONE);

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelSet,        0,
                       UMSTAG_SelUnset,      UMSFLAG_SEARCHTEMP,
                       TAG_DONE);

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelQuick,      TRUE,
                       UMSTAG_WFolder,       currentfolder,
                       UMSTAG_SelSet,        UMSFLAG_SEARCHTEMP,
                       UMSTAG_SelUnset,      0,
                       UMSTAG_SelReadGlobal, TRUE,
                       TAG_DONE);

   UMSSelectTags(login,UMSTAG_SelWriteLocal, TRUE,
                       UMSTAG_SelReadLocal,  TRUE,
                       UMSTAG_SelMask,       UMSFLAG_MATCHSEARCH | UMSFLAG_SEARCHTEMP,
                       UMSTAG_SelMatch,      UMSFLAG_MATCHSEARCH,
                       UMSTAG_SelSet,        0,
                       UMSTAG_SelUnset,      UMSFLAG_MATCHSEARCH,
                       TAG_DONE);

   num=countselected();

   if(num == 1)
      printf("%-40.40s --> %ld %s\n","Local",num,strings[STR_SELECTEDTEXT]);

   else
      printf("%-40.40s --> %ld %s\n","Local",num,strings[STR_SELECTEDTEXTS]);
}

long jbcpos;

short jbstrcpy(char *dest,char *src,long maxlen)
{
   long d=0;
   char stopchar1,stopchar2;

   while(src[jbcpos]==32 || src[jbcpos]==9) jbcpos++;

   if(src[jbcpos]=='"')
   {
      jbcpos++;
      stopchar1='"';
      stopchar2=0;
   }
   else
   {
   	stopchar1=' ';
   	stopchar2=9;
   }

   while(src[jbcpos]!=stopchar1 && src[jbcpos]!=stopchar2 && src[jbcpos]!='\n' && src[jbcpos]!=0 && d<maxlen-1)
   {
      if(src[jbcpos]=='\\' && src[jbcpos+1]!=0 && src[jbcpos+1]!='\n')
      {
         jbcpos++;
         dest[d++]=src[jbcpos++];
      }

      else
         dest[d++]=src[jbcpos++];
   }
   dest[d]=0;
   if(src[jbcpos]==9 || src[jbcpos]==' ' || src[jbcpos]=='"') jbcpos++;

   if(d!=0 || stopchar1=='"') return(TRUE);

   return(FALSE);
}

char selectbuf[1000];

void kom_select(char *arg,char *data)
{
   bool done;
   long c;

   if(!arg)
   {
      printf(strings[STR_NEEDSARG]);
      return;
   }

   if(stricmp(arg,strings[STR_SELECTNONE])==0)
   {
      if(!nextselected())
      {
         printf(strings[STR_UNSELECTNOSELECT]);
      }
      else
      {
         umsflag_clearsearch();
         printf(strings[STR_UNSELECTDONE]);
      }

      return;
   }

   jbcpos=0;

   jbstrcpy(selectbuf,arg,10);

   if(stricmp(selectbuf,"+")==0)
   {
      if(!nextselected())
      {
         printf(strings[STR_SELECTPLUSNOSELECTED]);
         return;
      }

      printf(strings[STR_SELECTPLUS],countselected());
      printf("\n");
   }
   else
   {
      jbcpos=0;
      umsflag_setsearchall();
   }


   brk=FALSE;

   while(jbstrcpy(selectbuf,arg,100) && !brk)
   {
      done=FALSE;

      if(!done)
      {
         for(c=0;selectflags[c].name;c++)
         {
            if(stricmp(selectflags[c].name,selectbuf)==0)
               break;

            if(selectbuf[0]=='!' && stricmp(selectflags[c].name,&selectbuf[1])==0)
               break;
         }

         if(selectflags[c].name)
         {
            done=TRUE;

            if(selectbuf[0]=='!')
               SelectFlagsUnset(&selectflags[c]);

            else
               SelectFlagsSet(&selectflags[c]);
         }
      }

      if(!done)
      {
         for(c=0;selectfields[c].name;c++)
         {
            if(stricmp(selectfields[c].name,selectbuf)==0)
               break;
         }

         if(selectfields[c].name)
         {
            if(!jbstrcpy(selectbuf,arg,1000))
            {
               printf(strings[STR_SELECTMISSINGSTRING],selectfields[c].name);
               return;
            }

            done=TRUE;
            SelectField(&selectfields[c],selectbuf);
         }
      }

      if(!done && stricmp(selectbuf,"Age")==0)
      {
         if(!jbstrcpy(selectbuf,arg,1000))
         {
            printf(strings[STR_SELECTMISSINGSTRING],selectfields[c].name);
            return;
         }

         if(!isnum(selectbuf))
         {
            printf(strings[STR_SELECTNEEDSNUM],"Age");
            return;
         }

         done=TRUE;
         SelectAge(atol(selectbuf));
      }

      if(!done && stricmp(selectbuf,"ParentOwner")==0)
      {
         done=TRUE;
         SelectParentOwner();
      }

      if(!done && stricmp(selectbuf,"Local")==0)
      {
         done=TRUE;
         SelectLocal();
      }

      if(!done)
      {
         printf(strings[STR_SELECTUNKNOWN],selectbuf);
         return;
      }
   }

   if(brk)
      printf(strings[STR_BREAK]);

   printf("\n");
   printf(strings[STR_SELECTTOTAL],countselected());
}
