/*
 * Round-trips the JS writer's real output through the C reader.
 *
 * The writer (src/pkjs/index.js) and the reader (src/c/main.c) are two implementations
 * of one format, in two languages, that never run in the same process. Nothing but a
 * test like this can catch them drifting apart — and drift decodes as plausible-looking
 * garbage rather than as an error, which is the failure worth spending a harness on.
 *
 * Build: see run-tests.sh. Reads the payload as hex on stdin.
 */
#include "pebble_stub.h"

/* main.c includes <pebble.h>; the build passes -include pebble_stub.h and -Dpebble_h
   so that include resolves to nothing. See run-tests.sh. */
#define main pebble_main   /* keep main.c's entry point out of the way */
#include "../src/c/main.c"
#undef main

static int failures = 0;

static void check(const char *label, bool ok) {
  printf("  %s %s\n", ok ? "PASS" : "FAIL", label);
  if (!ok) failures++;
}

int main(void) {
  static uint8_t buffer[4096];
  uint16_t length = 0;
  unsigned int byte;
  while (scanf("%2x", &byte) == 1 && length < sizeof(buffer)) buffer[length++] = (uint8_t)byte;

  printf("payload: %u bytes\n", length);
  bool ok = parse_plan(buffer, length);
  check("parses", ok);
  if (!ok) { printf("  status: %s\n", s_status); return 1; }

  check("room count is 3", s_room_count == 3);
  check("room 0 is named Kitchen", strcmp(s_rooms[0].name, "Kitchen") == 0);
  check("room 0 is occupied", s_rooms[0].state == 1);
  check("room 0 has 4 vertices", s_rooms[0].vertex_count == 4);
  check("room 0 has 1 occupant", s_rooms[0].occupant_count == 1);
  check("occupant initial is A", s_rooms[0].occupants[0].initial == 'A');
  check("occupant colour index 0", s_rooms[0].occupants[0].colour == 0);
  check("occupant has a position", s_rooms[0].occupants[0].has_position);
  check("occupant name survived", strcmp(s_rooms[0].occupants[0].name, "Amir") == 0);

  check("room 1 is named Loggia", strcmp(s_rooms[1].name, "Loggia") == 0);
  /* A radar target outranks "HA never reports this area": somebody IS in there, and a
     positive detection beats no data. The first draft of this test asserted the
     opposite and was wrong. */
  check("room 1 is occupied (radar, nobody named)", s_rooms[1].state == 1);
  check("room 1 has an anonymous target", s_rooms[1].target_count == 1);
  check("room 1 has no occupants", s_rooms[1].occupant_count == 0);

  check("room 2 is the unknown state", s_rooms[2].state == 2);
  check("room 2 has no targets", s_rooms[2].target_count == 0);

  check("1 unplaced person", s_unplaced_count == 1);
  check("unplaced is Bibi", strcmp(s_unplaced[0].name, "Bibi") == 0);

  /* A truncated payload must be refused wholesale, never half-decoded: a plan missing
     its last rooms looks exactly like a real plan. */
  bool truncated = parse_plan(buffer, length / 2);
  check("truncated payload refused", !truncated && s_room_count == 0);

  /* A version bump on the phone must not decode as garbage here. */
  buffer[0] = 99;
  check("wrong version refused", !parse_plan(buffer, length));

  printf(failures ? "\nFAILURES: %d\n" : "\nall wire-format checks passed\n", failures);
  return failures ? 1 : 0;
}
