#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "prtrans.h"

#if !defined(__MAIN_C__)
#define main	main_prwfile
#endif

#if defined(__MAIN_C__)
unsigned char buffer[256];
#else
extern unsigned char buffer[];
#endif

int main(int argc, char **argv);

int
main(int argc, char **argv)
{
  FILE *file = stdout;
  int device = 8;
  int byte;
  char **parameters = argv;
  char *remotefile;
  char *localfile;
  char *portspecified = NULL;
  char *prg = "prwfile.prg"; /* loader program file name */
  int specified_remotefile = 0;
  baseaddr = portaddr[DEFAULT_PORT];

  while (*++parameters && **parameters == '-') { /* check for options */
    if (parameters[0][1] == '-') { /* "--" ends options */
      parameters++;
      break;
    }

    switch (parameters[0][1]) {
    case 'd':
      device = strtoul (*++parameters, NULL, 0);

      if (device > 15) {
	fprintf (stderr, "%s: Illegal device number specified.\n", *argv);
	return 1;
      }

      break;

    case 'l':
      prg = *++parameters;
      break;

    case 'p':
      baseaddr = strtoul (*++parameters, NULL, 16);

      if (baseaddr > 3) {
	fprintf (stderr, "%s: The printer port number must be between 0 and 3.\n",
			 *argv);
	return 1;
      }

      portspecified = *parameters;
      baseaddr = portaddr[baseaddr];
      break;

    case '?':
    case 'h':
    Usage:
      fprintf (stderr, "%s: Writes a local file to a file on a remote "
		       "computer.\n\n", *argv);
      fprintf (stderr, "Usage: %s [options] filename [remote filename]\n",
		       *argv);
      fprintf (stderr, "Options:\n\t"
			 "-d device\t"
			     "Specify the device number (0-15)\n\t"
			 "-l filename\t"
			     "Specify the filename of the client program\n\t"
			 "-p port\t"
			     "Specify the printer port (0 to 3)\n");
      fprintf (stderr, "The remote filename is converted to PETSCII.\n");

      return 1;

    default:
      fprintf (stderr, "%s: Illegal option `%s'.\n", *argv, *parameters);
      goto Usage;
    }
  }

  if (!*parameters) goto Usage;

  localfile = *parameters++;
  remotefile = strdup(localfile);

  if (*parameters) {
    remotefile = *parameters++;
    specified_remotefile = 1;
  }
  ascii2petscii(remotefile);

  if (!specified_remotefile && localfile[1] == ':') {
    localfile += 2;	/* strip 0: or 1: from local filename */
  }
  if (strcmp(localfile, "-") == 0) {
    file = stdout;
  } else if (!(file = fopen(localfile, "rb"))) {
    fprintf (stderr, "%s: Could not open the file `%s'.\n", *argv,
		       localfile);
    return 1;
  }

  {
    int addr;

    FILE *f = fopen(prg, "r");
    if (f == NULL) {
      fprintf (stderr, "%s: Cannot find %s to download\n", *argv, prg);
      return 1;
    }

    addr = fgetc(f);
    addr |= fgetc(f) << 8;
    fclose(f);

#if defined(__MAIN_C__)
    {
      char cmd[80];
      sprintf(cmd, "prload -j %x ", addr);

      if (portspecified) {
	strcat (cmd, "-p ");
	strcat (cmd, portspecified);
	strcat (cmd, " ");
      }

      strcat (cmd, prg);

      fprintf (stderr, "%s\n", cmd);
      system(cmd);
    }
#else
    {
      char saddr[10];
      sprintf(saddr, "%x", addr);
      vmain (main_prload, 4, "prload", "-j", saddr,
	     portspecified ? "-p", portspecified, prg, NULL : prg, NULL);
    }
#endif
  }

  if (prinit()) {
    fprintf (stderr, "%s: Could not get the I/O permissions.\n", *argv);
    return 1;
  }

  if (wait_input ()) {
    fprintf (stderr, "%s: not ready to transfer\n", *argv);
    return 6;
  }
  else
    fprintf (stderr, "%s: ok to transfer\n", *argv);

  byte = strlen(remotefile);
  output(byte);
  send(remotefile, byte);
  output(device);

  if ((byte = wait_input ()) != 0) {
    fprintf (stderr, "%s: file error %d\n", *argv, byte);
    return 1;
  }
  fprintf(stderr, "Writing %s to %s...\n", localfile, remotefile);

  /* loop to send all file blocks */
  for (;;) {
    int length;
    int chksum;
    int i;

    length = fread(buffer + 1, 1, 255, file);

    chksum = 0;
    for (i = 0; i < length; i++) {
      chksum += buffer[1 + i];
    }
    buffer[0] = chksum;

    for (;;) {
      output(length);

      if (length == 0)
	break;	      /* end of file */

      send(buffer, length + 1);

      i = wait_input();

      switch (i) {
      case 0x80:
	goto nextblock;
      case 0x81:
	fprintf(stderr, "checksum error, resending...\n");
	break;
      default:
	fprintf(stderr, "Aborting\n");
	goto abort;
      }
    }
  nextblock:
    if (length == 0)
      break;
  }
abort:

  fclose(file);

  output(0);	/* terminate remote side */

  prclose ();

  return 0;
}

