// cc -Wall -g -o findmean findmean.c -lm
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#ifdef __APPLE__
  #include <mach/error.h>
#else
  #include <error.h>
#endif
#include <errno.h>

static int verbose = 0;

static inline int iround(float num) {
  return (num - floor(num) > 0.5) ? ceil(num) : floor(num);
}

int main(int argc, char **argv) {
  int files=0;
  int rc;

  // first pass to determine limits
  {
    int lines, cols;
    static char fname[1024];
    float height, yoffset, width, xoffset;

    // AW-000.pnm 64.1 61.900000 64 39.8 24.200000 131
    rc = fscanf(stdin, "%s %f %f %d %f %f %d\n", fname, &height, &yoffset,
                &lines, &width, &xoffset, &cols);
    if (rc != 7) {
      fprintf(stderr, "Input should look something like: AW-000.pnm 64.1 "
                      "61.900000 64 39.8 24.200000 131\n");
      exit(EXIT_FAILURE);
    }
    errno = 0;
    rewind(stdin);
    if (errno != 0) {
      fprintf(stderr, "I'm going to stop you there before you waste a lot of "
                      "time... the input to this\n");
      fprintf(stderr, "program cannot come from a pipe.  Rerun the gridfinder "
                      "with output directed to\n");
      fprintf(stderr,
              "a file, and run this program with that file as input, e.g.:\n");
      fprintf(stderr, "\n");
      fprintf(
          stderr,
          "gridfinder pages/*.png > prescan.txt ; findmean < prescan.txt\n");
      fprintf(stderr, "\n");
      fprintf(stderr, "(Press ^C now if this doesn't immediately return to the "
                      "command line.)\n");
      fprintf(stderr, "\n");
      exit(EXIT_FAILURE);
    }

    for (;;) {
      // AW-000.pnm 64.1 61.900000 64 39.8 24.200000 131
      rc = fscanf(stdin, "%s %f %f %d %f %f %d\n", fname, &height, &yoffset,
                  &lines, &width, &xoffset, &cols);
      if (rc != 7)
        break;
      if (height > 0.0) files += 1;
    }
    errno = 0;
    rewind(stdin);
    if (errno != 0) {
      fprintf(stderr, "Unexpected error on second rewind - %s\n",
              strerror(errno));
    }
  }

  // second pass to fill array
  {
    int lines[files], cols[files];
    //char fname[1024][files];
    //char fname[files][1024];
    char *fname[files];
    int i;
    for (i = 0; i < files; i++) fname[i] = malloc(1023); 
    int height[files]; //, yoffset[files];
    int width[files]; //, xoffset[files];
    float fheight, fyoffset, fwidth, fxoffset;
    i = files-1; 
    for (;;) {
      // AW-000.pnm 64.1 61.900000 64 39.8 24.200000 131
      rc = fscanf(stdin, "%s %f %f %d %f %f %d\n", fname[i], &fheight, &fyoffset, &lines[i], &fwidth, &fxoffset, &cols[i]);
      if (rc != 7) break;
      if (fheight <= 0.0) {
        fprintf(stderr, "%s has an invalid height - it is probably a blank page and should be removed.\n", fname[i]);
        if (i == 0) break;
        continue;
      }
      height[i] = iround(fheight*10.0);
      //yoffset[i] = iround(fyoffset*10.0);
      width[i] = iround(fwidth*10.0);
      //xoffset[i] = iround(fxoffset*10.0);
      if (i == 0) break;
      i -= 1;
    }
    if (i != 0) {
      fprintf(stderr, "Didn't get the same number of lines on the second pass as we did on the first?\n");
      exit(EXIT_FAILURE);
    }

    // Now we try to find the most common line and column spacing from the examined pages...
    if (verbose >= 2) {
    for (i = 0; i < files; i++) {
      fprintf(stderr, "(%d.%0dx%d.%0d) ",  height[i]/10,height[i]%10, width[i]/10,width[i]%10);
    }
    fprintf(stderr, "\n");
    }
    int lowest = 0x7FFFFFFF, highest = 0;
    for (i = 0; i < files; i++) {
      if (height[i] < lowest) {
        lowest = height[i];
      }
      if (height[i] > highest) {
        highest = height[i];
      }
    }
    if (lowest == 0x7FFFFFFF ||  highest == 0) {
      fprintf(stderr, "Could not find highest and lowest line spacings.\n");
      exit(EXIT_FAILURE);
    }
    if (verbose >= 1) fprintf(stderr, "Height range from %d.%0d to %d.%0d\n", lowest/10,lowest%10, highest/10,highest%10);
    int height_freq[highest-lowest+1];
    for (i = lowest; i <= highest; i++) {
      height_freq[i-lowest] = 0;
    }
    for (i = 0; i < files; i++) {
      height_freq[height[i]-lowest] += 1;
    }
    int bestindex = -1, bestheight_freq = 0;
    for (i = lowest; i <= highest; i++) {
      if (verbose >= 2) {
      if (height_freq[i-lowest]) {
        fprintf(stderr, "[%d.%0d: %d] ", i/10,i%10, height_freq[i-lowest]);
      }
      }
      if (height_freq[i-lowest] > bestheight_freq) {
        bestheight_freq = height_freq[i-lowest]; bestindex = i;
      }
    }
    if (verbose >= 2) fprintf(stderr, "\n");
    fprintf(stdout, "%d.%0d ", bestindex/10, bestindex%10);

    lowest = 0x7FFFFFFF; int widest = 0;
    for (i = 0; i < files; i++) {
      if (width[i] < lowest) {
        lowest = width[i];
      }
      if (width[i] > widest) {
        widest = width[i];
      }
    }
    if (lowest == 0x7FFFFFFF ||  highest == 0) {
      fprintf(stderr, "Could not find highest and lowest column spacings.\n");
      exit(EXIT_FAILURE);
    }
    if (verbose >= 1) fprintf(stderr, "width range from %d.%0d to %d.%0d\n", lowest/10,lowest%10, widest/10,widest%10);
    int width_freq[widest-lowest+1];
    for (i = lowest; i <= widest; i++) {
      width_freq[i-lowest] = 0;
    }
    for (i = 0; i < files; i++) {
      width_freq[width[i]-lowest] += 1;
    }
    bestindex = -1; int bestwidth_freq = 0;
    for (i = lowest; i <= widest; i++) {
      if (verbose >= 2) {
      if (width_freq[i-lowest]) {
        fprintf(stderr, "[%d.%0d: %d] ", i/10,i%10, width_freq[i-lowest]);
      }
      }
      if (width_freq[i-lowest] > bestwidth_freq) {
        bestwidth_freq = width_freq[i-lowest]; bestindex = i;
      }
    }
    if (verbose >= 2) fprintf(stderr, "\n");
    fprintf(stdout, "%d.%0d\n", bestindex/10, bestindex%10);

    for (i = 0; i < files; i++) free(fname[i]);
  }
  exit(EXIT_SUCCESS);
  return EXIT_FAILURE;
}
