#include <proto/exec.h>
#include <exec/memory.h>
#include <proto/dos.h>
#include <proto/xpk.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct Library *XpkBase = NULL;

char errbuf[XPKERRMSGSIZE + 1], *ibuf = NULL, *obuf = NULL;
long ibuflen, obuflen;
BPTR fh = 0;

void 
print (char *s)
{
  Write (Output (), s, strlen (s));
}

void 
end (char *text)
{
  if (fh)
    Close (fh);
  if (ibuf)
    FreeMem (ibuf, ibuflen);
  if (obuf)
    FreeMem (obuf, obuflen);
  if (text) {
    print (text); print (errbuf); print ("\n");
  }
  if (XpkBase)
    CloseLibrary (XpkBase);
  exit (text ? 10 : 0);
}

static char * xpkprogname[4] = { "unknown", "Start:", "Mid  :", "End  :"} ;

long __asm
chunkfunc (register __a1 struct XpkProgress *prog)
{
  char buf[120];

  print (xpkprogname[prog->Type]);

  switch (prog->Type) {
  case XPKPROG_START:
    print ("Start:");
    break;
  case XPKPROG_MID:
    print ("Mid  :");
    break;
  case XPKPROG_END:
    print ("End  :");
    break;
  }
  if (prog->Type != XPKPROG_END)
    sprintf (buf, "\r%4s: %-8s (%3ld%% done, %2ld%% CF, %6ld cps) %s\n",
	     prog->PackerName, prog->Activity, prog->Done,
	     prog->CF, prog->Speed, prog->FileName);
  else
    sprintf (buf,
	     "\r%4s: %-8s (%3ldK, %2ld%% CF, %6ld cps) %s\033[K\n",
	     prog->PackerName, prog->Activity, prog->ULen / 1024,
	     prog->CF, prog->Speed, prog->FileName);

  print (buf);

  return (long) SetSignal (0, SIGBREAKF_CTRL_C) & SIGBREAKF_CTRL_C;
}
struct Hook chunkhook = { {0}, chunkfunc };

void 
main (int argc, char *argv[])
{
  struct XpkFib xfib;
  struct FileInfoBlock fib;
  ULONG ilen, olen;
  int errcode;

  errbuf[0] = 0;

  if (!(XpkBase = OpenLibrary (XPKNAME, 0)))
    end ("Cannot open " XPKNAME "\n");

  if (argc != 4)
    end ("Usage: testMemPack infilename method outfilename\n");

  if (!(fh = Open (argv[1], MODE_OLDFILE)))
    end ("Cannot open input file");

  if (!(ExamineFH (fh, &fib)))
    end ("Failed to ExamineFH input file");

  ibuflen = fib.fib_Size;

  if (!(ibuf = AllocMem (ibuflen, MEMF_ANY)))
    end ("Out of memory");

  ilen = Read (fh, ibuf, ibuflen);

  if (ilen != ibuflen)
    end ("Could not read whole file with one Read()");

  Close (fh); fh = 0;

  if (XpkExamineTags( &xfib,
		      XPK_InBuf, ibuf,
		      XPK_InLen, ibuflen,
                      XPK_GetError, errbuf,
		      TAG_DONE
		    ))
    end ("Can't XpkExamine");
    
  if (errcode = XpkPackTags (XPK_InBuf, ibuf,
                   XPK_InLen, ilen,
                   XPK_PackMethod, argv[2],
                   XPK_GetOutBuf, &obuf,
                   XPK_GetOutBufLen, &obuflen,
                   XPK_GetOutLen, &olen,
                   XPK_GetError, errbuf,
                   XPK_ChunkHook, &chunkhook,
                   TAG_DONE)) {
    fprintf(stderr, "errcode: %d\n", errcode);
    end ("Can't XpkPackTags");
  }

  if (!(fh = Open (argv[3], MODE_NEWFILE)))
    end ("Can not create output file");

  if (Write (fh, obuf, olen) != olen)
    end ("Can not Write output");

  Close (fh); fh =0;

  end (NULL);
}
