#include <aspoprotocol.h>
#include <stdlib.h>

#define LOG_BUFSZ 200
const size_t log_bufsz = LOG_BUFSZ;
char log_buffer[LOG_BUFSZ];

uint8_t buf[S6400_MAXREQLEN];
#define STRLEN 4000
char str[STRLEN];

void printhex(const uint8_t *buffer, size_t len);
void Usage(void);

void printhex(const uint8_t *buffer, size_t len) {
  const uint8_t *p = buffer;
  const uint8_t *end = buffer + len;
  printf("%d <", len);
  while (p < end) printf("%02X", *p++);
  printf(">\n");
  fflush(stdout);
}

void Usage(void) {
  printf("Usage:\n"
	 "\tTestgeneric [mode] [cmd] [serial] [uid] [data]\n"
	 "\twhere data is a hex string and have an even number of chars\n"
	 );
  exit(1);
}

int main(int argc, char *argv[]) {
  int val;
  int bufsize = S6400_MAXREQLEN;
  uint8_t mode = 0;
  uint8_t cmd = 0;
  uint32_t serial = 0;
  uint64_t uid = 0;
  uint8_t data[S6400_MAXREQLEN - 8];
  size_t data_len = 0;
  char *pp;
  uint8_t *qq;

  log_open(NULL, LOG_PRIO | 2, 0);

  val = 1;
  if (argc >= ++val) LOG_IFERRNO( (mode = strtoul(argv[val-1], &pp, 0), errno), LOG_CRIT ) Usage();
  if (argc >= ++val) LOG_IFERRNO( (cmd = strtoul(argv[val-1], &pp, 0), errno), LOG_CRIT ) Usage();
  if (argc >= ++val) LOG_IFERRNO( (serial = strtoul(argv[val-1], &pp, 0), errno), LOG_CRIT ) Usage();
  LOG_IF( serial >= 10000000, LOG_ERR ) return -1;
  if (argc >= ++val) LOG_IFERRNO( (uid = strtoull(argv[val-1], &pp, 16), errno), LOG_CRIT ) Usage();
  if (argc >= ++val) {
    if ( strlen(argv[val-1]) % 2 ) Usage();
    for ( pp = argv[val-1], qq = data; sscanf( pp, "%2hhx", qq) != EOF; pp += 2, ++qq) { }
    data_len = qq - data;
  }
  s6400_default_flags |= mode & 0x0f;

  printf("\tTesting 10 error situations:\n");
  s6400_addlrc( NULL);
  s6400_addlrc( buf);
  buf[0] = SOH;
  s6400_addlrc( buf);

  buf[0] = 0;
  s6400_validate(NULL, bufsize);
  s6400_validate(buf, bufsize);
  buf[0] = SOH;
  s6400_validate(buf, bufsize);
  buf[1] = 8;
  s6400_validate(buf, bufsize);

  s6400_generic_req(NULL, bufsize, cmd, serial, uid, data, data_len);
  s6400_generic_req(buf, 2, cmd, serial, uid, data, data_len);
  s6400_generic_req(buf, 4000, cmd, serial, uid, data, 2000);


  printf("\n\tValues used: 0x%02X 0x%02X %7d 0x%016llX ", mode, cmd, serial, uid);
  for (qq = data; qq < data+data_len; qq++) printf("%02X", *qq);
  printf("\n");

  val = s6400_generic_req(buf, bufsize, cmd, serial, uid, data, data_len);
  printhex(buf, S6400_PACKETLENGTH(buf));
  printf("s6400_generic_req() = %d\n", val);
  val = s6400_validate(buf, bufsize);
  printf("s6400_validate() = %d\n", val);

  return 0;
}
