#include <stdlib.h>
#include <libraries/xpkarchive.h>

struct Library *XpkArchiveBase;

#define BUFSIZE 4096L

char buffer[BUFSIZE];

int   chkabort(void) { return 0; }           /* disable SAS ^C handling */
long __asm chunkfunc(register __a1 struct XpkProgress *prog);

struct Hook chunkhook = {{0},chunkfunc};

main(argc,argv)
int argc;
char *argv[];
{
   XarHandle *arc;
   short a;
   short uncompress=0;
   short list=0;
   int base=1;
   long err;

   char *mode="";

   if(argc<3) {
      printf("Usage: %s [-m|-x|-l] <archive> <file1> [<file2> ...]\n",argv[0]);
      exit(0);
   }

   if(!strcmp("-m",argv[1])) {
      mode=argv[2];
      base=3;
   } else if(!strcmp("-l",argv[1])) {
      list=1;
      base=2;
   } else if(!strcmp("-x",argv[1])) {
      uncompress=1;
      base=2;
   }


   if(!(XpkArchiveBase=OpenLibrary("xpkarctest.library",0L))) {
      fprintf(stderr,"Cannot open xpkarctest.library\n");
      exit(0);
   }

   if(!(arc=XarOpenArchive(XAR_ArchiveName,argv[base],
                            XAR_ArchiveMode,XAR_ModeAppend,
                            XAR_ShowDirs,TRUE,
                            TAG_DONE))) {
      printf("Could not create archive\n");
      CloseLibrary(XpkArchiveBase);
      exit(0);
   }

   printf("Informational: %s\n",XarWhy(arc));

   if(list) {
      ULONG sum1=0,sum2=0;
      float ratio;
      XarLock *lock;
      struct XarFileData *data;
      puts("Original Packed Ratio  Date     Time   Gen Mode Name\n"
           "-------- ------ ---- -------- -------- --- ---- ----------");
      for(lock=XarGetLock(arc);lock;lock=XarNextLock(lock)) {
         ULONG compsize;

         data=XarGetFileData(lock);
         compsize=XarGetFileSize(lock);
         sum1+=data->Filesize;
         sum2+=compsize;

         if(data->Filesize==0) ratio=0; else ratio=100.0-100*(float)compsize/data->Filesize;
         if(XarIsXpkArchive(arc)) {
            ULONG pname[2];
            struct XpkFib fib;
            XarExamine(lock,&fib);
            pname[0]=fib.ID;
            pname[1]=0;
            printf("%8lu %6lu %2.1f %2d.%02d.%02d %2d:%02d:%02d %3d %4s %s\n",
                    data->Filesize,compsize,ratio,data->Time.Day,data->Time.Month,
                    data->Time.Year,data->Time.Hour,data->Time.Min,data->Time.Sec,
                    data->Generation,pname,XarGetFileName(lock));
         } else {
            printf("%8lu %6lu %2.1f %2d.%02d.%02d %2d:%02d:%02d %3d %4d %s\n",
                    data->Filesize,compsize,ratio,data->Time.Day,data->Time.Month,
                    data->Time.Year,data->Time.Hour,data->Time.Min,data->Time.Sec,
                    data->Generation,data->Flags,XarGetFileName(lock));
         }
         if(XarGetFileNote(lock)) puts(XarGetFileNote(lock));
      }
      puts("-------- ------ ----");
      if(sum1==0) ratio=0; else ratio=100.0-100*(float)sum2/sum1;
      printf("%8lu %6lu %2.1f\n",sum1,sum2,ratio);
   } else if(uncompress) {
      for(a=base+1;a<argc;a++) {
         char tmp[100],*p;
         int gen=0;
         strcpy(tmp,argv[a]);
         if(p=rindex(tmp,',')) {
            if(sscanf(p+1,"%d",&gen)!=1) {
               fprintf(stderr,"Invalid generation\n");
               goto ExitFail;
            }
            *p=0;
         }
         printf("Generation %d\n",gen);
         if(XarExtractFile(XAR_OutName,argv[a],XAR_FileName,tmp,
                    XAR_Generation,(ULONG)gen,
                    XAR_Archive,arc,
                    XAR_ProgressHook,&chunkhook,
                    TAG_DONE)) printf("Error: %s\n",XarWhy(arc));
      }
   } else {
      for(a=base+1;a<argc;a++) {
         char *basename,*p;
         p=index(argv[a],':');
         basename=p?p+1:argv[a]; /* Name without volume name */
         if(*basename=='/') basename++;

         if(!XarAddFile(XPK_InName,argv[a],XAR_FileName,basename,
                    XAR_Archive,arc,
                    XAR_PackMethod,mode,
                    XAR_ProgressHook,&chunkhook,TAG_DONE))

               printf("Error: %s\n",XarWhy(arc));

      }
   }
ExitFail:
   XarCloseArchive(arc);
   CloseLibrary(XpkArchiveBase);
}


long __asm chunkfunc(register __a1 struct XpkProgress *prog)
{
   if( prog->Type!=XPKPROG_END ) {
      printf("%4s: %-8s (%3ld%% done, %2ld%% CF, %6ld cps) %s\033[K\r",
         prog->PackerName,  prog->Activity,   prog->Done,
         prog->CF,          prog->Speed,      prog->FileName);
      fflush(stdout);
   } else {
      printf("%4s: %-8s (%3ldK, %2ld%% CF, %6ld cps) %s\033[K\n",
         prog->PackerName,  prog->Activity,   prog->ULen/1024,
         prog->CF,          prog->Speed,      prog->FileName);

   }
   return (long)SetSignal(0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C;
}

