#define PCRE2_CODE_UNIT_WIDTH 8

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

typedef struct Pattern {
  const char *name;
  pcre2_code *re;
} Pattern;

char *read_file(const char *filename) {
  FILE *fp = fopen(filename, "rb");
  if (!fp) {
    perror("fopen");
    return NULL;
  }
  fseek(fp, 0, SEEK_END);
  long size = ftell(fp);
  rewind(fp);
  char *buffer = malloc(size + 1);
  if (!buffer) {
    perror("malloc");
    fclose(fp);
    return NULL;
  }
  size_t read = fread(buffer, 1, size, fp);
  buffer[read] = '\0';
  fclose(fp);
  return buffer;
}

int main() {
  const char *pattern = "\\b(class)\\s+(([a-zA-Z0-9_]+)((::[a-zA-Z0-9_]+)*))"
                        "\\s*((<)\\s*(([a-zA-Z0-9_]+)((::[a-zA-Z0-9_]+)*))?)?";
  const char *input = read_file("/home/syed/main/cubit/tests/test.rb");

  int errorcode;
  PCRE2_SIZE erroroffset;

  // Compile the regex
  pcre2_code *re = pcre2_compile((PCRE2_SPTR)pattern,   // pattern
                                 PCRE2_ZERO_TERMINATED, // pattern length
                                 0,                     // options
                                 &errorcode,            // for error code
                                 &erroroffset,          // for error offset
                                 NULL                   // compile context
  );

  if (!re) {
    PCRE2_UCHAR buffer[256];
    pcre2_get_error_message(errorcode, buffer, sizeof(buffer));
    fprintf(stderr, "PCRE2 compilation failed at offset %d: %s\n",
            (int)erroroffset, buffer);
    return 1;
  }

  // Prepare match data
  pcre2_match_data *match_data = pcre2_match_data_create_from_pattern(re, NULL);

  int rc = pcre2_match(re,                // the compiled pattern
                       (PCRE2_SPTR)input, // subject string
                       strlen(input),     // length of subject
                       0,                 // start offset
                       0,                 // options
                       match_data,        // match data
                       NULL               // match context
  );

  if (rc < 0) {
    printf("No match found.\n");
  } else {
    PCRE2_SIZE *ovector = pcre2_get_ovector_pointer(match_data);
    for (int i = 0; i < rc; i++) {
      PCRE2_SIZE start = ovector[2 * i];
      PCRE2_SIZE end = ovector[2 * i + 1];
      printf("Group %d: start=%lu end=%lu text=\"%.*s\"\n", i, start, end,
             (int)(end - start), input + start);
    }
  }

  // Cleanup
  pcre2_match_data_free(match_data);
  pcre2_code_free(re);

  return 0;
}
