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

#ifndef THRESH
#define THRESH 0
#endif

static int debug_level = 0;

static int max3(int a, int b, int c) {
  if ((a > b) && (a > c)) return a;
  if (b > c) return b;
  return c;
}

#define SP ' '
#define PX '@'
#define XS SP // '.'
#define NO SP // 'C'

int main(int argc, char **argv) {
  int i, j;
  const char *f[128];
  for (i = 0; i < 128; i++) f[i] = NULL;

  // This is an initial phase of recognition where one glyph is manually
  // chosen by inspection from the html map, to be used for initial
  // identification.

  // We will then use that to collect multiple instances of each glyph
  // (which will almot certainly require manual filtering to remove
  //  misidentified matches).
  // Those can then be used for two purposes:
  // 1) training a neural net recogniser
  // 2) composing an 'ideal' glyph by averaging multiple (aligned)
  //    instances of a glyph.  I'm hoping that this will remove a
  //    lot of the noise and produce a cleaner master.  Manual setting
  //    of the threshold level may be needed to extract the best image.
  
  f[' '] = "AW-004/line001/col040.png";
  f['"'] = "AW-002/line029/col055.png";
  f['#'] = "AW-001/line023/col057.png";
  f['$'] = "AW-025/line017/col089.png"; //  AW-031/line016/col003.png";
  f['%'] = "AW-025/line023/col066.png";
  f['&'] = "AW-015/line023/col088.png"; // AW-006/line017/col024.png AW-030/line020/col024.png";
  f['\''] = "AW-000/line001/col038.png";
  f['('] = "AW-003/line032/col064.png"; "AW-001/line039/col057.png";
  f[')'] = "AW-001/line032/col058.png";
  f['*'] = "AW-000/line008/col017.png";
  f['+'] = "AW-002/line035/col076.png";
  f[','] = "AW-001/line023/col072.png"; //"AW-005/line025/col064.png";
  f['-'] = "AW-001/line031/col060.png";
  f['.'] = "AW-002/line053/col113.png"; //"AW-000/line009/col015.png"; // AW-032/line010/col031.png";
  f['/'] = "AW-000/line007/col002.png";
  f['0'] = "AW-004/line008/col032.png";
  f['1'] = "AW-000/line005/col038.png";
  f['2'] = "AW-000/line001/col031.png";
  f['3'] = "AW-012/line018/col012.png";
  f['4'] = "AW-004/line006/col033.png";
  f['5'] = "AW-004/line046/col059.png";
  f['6'] = "AW-004/line010/col048.png";
  f['7'] = "AW-000/line011/col007.png";
  f['8'] = "AW-002/line012/col018.png"; //"AW-004/line023/col048.png";
  f['9'] = "AW-004/line020/col052.png";
  f[':'] = "AW-001/line051/col066.png";
  f[';'] = "AW-001/line058/col061.png";
  f['<'] = "AW-001/line056/col087.png";
  f['='] = "AW-001/line052/col077.png";
  f['>'] = "AW-001/line040/col069.png";
  f['@'] = "AW-002/line032/col063.png";
  f['A'] = "AW-002/line006/col057.png";
  f['B'] = "AW-001/line021/col069.png"; //"AW-002/line025/col052.png";
  f['C'] = "AW-001/line050/col048.png"; //"AW-002/line027/col051.png";
  f['D'] = "AW-002/line049/col052.png";
  f['E'] = "AW-001/line015/col052.png"; //"AW-004/line012/col046.png";
  f['F'] = "AW-003/line013/col055.png"; "AW-004/line010/col059.png";
  f['G'] = "AW-000/line011/col013.png"; // "AW-008/line030/col055.png";
  f['H'] = "AW-009/line008/col069.png";
  f['I'] = "AW-001/line040/col067.png"; //"AW-019/line029/col071.png";
  f['J'] = "AW-009/line008/col082.png";
  f['K'] = "AW-009/line041/col085.png";
  f['L'] = "AW-009/line041/col082.png";
  f['M'] = "AW-009/line050/col087.png";
  f['N'] = "AW-009/line031/col093.png";
  f['O'] = "AW-000/line011/col014.png"; //"AW-006/line015/col038.png";
  f['P'] = "AW-020/line021/col067.png";
  f['Q'] = "AW-022/line027/col052.png";
  f['R'] = "AW-004/line003/col051.png";
  f['S'] = "AW-009/line029/col090.png";
  f['T'] = "AW-009/line029/col081.png";
  f['U'] = "AW-009/line045/col066.png";
  f['V'] = "AW-021/line010/col052.png";
  f['W'] = "AW-009/line052/col075.png";
  f['X'] = "AW-021/line021/col082.png"; // AW-022/line031/col059.png";
  f['Y'] = "AW-021/line036/col091.png";
  f['Z'] = "AW-021/line015/col065.png";
  f['\\'] = "AW-001/line052/col076.png";
  f['|'] = "AW-088/line051/col082.png"; // AW-113/line020/col061.png AW-136/line050/col067.png
  f['_'] = "AW-001/line057/col057.png"; // AW-089/line060/col063.png

  printf("#ifndef NULL\n");
  printf("#define NULL 0\n");
  printf("#endif\n\n");

  printf("typedef struct asciimap {\n");
  printf("  int ch;\n");
  printf("  const char *f;\n");
  printf("  const char *line[100]; // *UP TO* 45 lines.\n");
  printf("} asciimap;\n\n");

  printf("const asciimap C[128] = {\n");
  for (i = 0; i <= 127; i++) {
    printf("  {\n");
    if (i < 32 || i >= 127) {
      printf("    %d, ", i);
    } else {
      printf("    '%s%c', ", i=='\'' || i=='\\' ? "\\" : "", i);
    }
    if (f[i] == NULL) printf(" NULL,\n"); else  printf(" \"%s\",\n", f[i]);
    if (f[i]) {
      FILE *png;
      static char fname[1024];
      sprintf(fname, "convert ../testsplit/tiles/%s txt:-", f[i]);
      png = popen(fname, "r");
      if (png == NULL) {
        printf("      {\n");
        //for (j = 0; j < 45; j++) {
        //  printf("    \"                                                      \",\n");
        //}
        printf("        NULL,\n");
        printf("      },\n");
      } else {
        static char line[128];
        int c;
        int maxx, maxy, maxbyte, x, y, r, g, b;
        // # ImageMagick pixel enumeration: 40,67,255,gray
        // 0,0: (255,255,255)  #FFFFFF  gray(255)
        int p;
        printf("    {\n");
        for (;;) {
          p = 0;          
          for (;;) {
            c = fgetc(png);
            if (c == EOF || c == '\n' || ferror(png)) break;
            line[p++] = c;
          }
          line[p] = '\0';
          if (c != '\n') break;
          if (line[0] == '#') {
            // "# ImageMagick pixel enumeration: 40,67,255,gray"
            int rc = sscanf(line, "# ImageMagick pixel enumeration: %d,%d,%d,"/*gray*/,
                            &maxx, &maxy, &maxbyte);
            if (rc == 3) {
              if (debug_level >= 1) fprintf(stderr, "%d x %d (%d)\n", maxx, maxy, maxbyte);
              //P.width = maxx; P.height = maxy;
            } else {
              exit(1); 
            }
          } else {
            // "0,0: (255)  #FFFFFF  gray(255)"
            int rc = sscanf(line, "%d,%d: (%d,%d,%d)"/*  #FFFFFF  gray(255)*/, &x, &y, &r, &g, &b);
            if (rc == 5) {
              if (debug_level >= 2) printf("x=%d y=%d: r=%d/g=%d/b=%d\n", x, y, r, g, b);
              if ((x >= maxx || x < 0) || (y >= maxy || y < 0)) {
                // index out of range
                if (debug_level >= 2) fprintf(stderr, "png2h: pixel (%d,%d) out of range (0:%d,0:%d):  %s\n\n", x,y, maxx-1,maxy-1, line);
              } else {
                if (x == 0) printf("      \"");
                if (max3(r,g,b) > THRESH) putchar('@'); else putchar(' ');
                if (x == maxx-1)  printf("\",\n");
              }
            } else {
              rc = sscanf(line, "%d,%d: (%d)"/*  #FFFFFF  gray(255)*/, &x, &y, &g);
              if (rc == 3) {
                if (debug_level >= 2) printf("x=%d y=%d: g=%d\n", x, y, g);
                if ((x >= maxx || x < 0) || (y >= maxy || y < 0)) {
                  // index out of range
                  if (debug_level >= 2) fprintf(stderr, "png2h: pixel (%d,%d) out of range (0:%d,0:%d):  %s\n\n", x,y, maxx-1,maxy-1, line);
                } else {
                  if (x == 0) printf("      \"");
                  if (g > THRESH) putchar('@'); else putchar(' ');
                  if (x == maxx-1)  printf("\",\n");
                }
              } else {
                exit(1);
              }
            }
          }
          
        }
        fclose(png);
        printf("      NULL,\n    },\n");
        //for (j = 0; j < 45; j++) {
        //}
      }
    } else {
      printf("    {\n      NULL\n    }\n");
    }
    printf("  },\n");
  }
  printf("};\n");
}
