#include "tree_sitter/parser.h"

#include <stdbool.h>
#include <ctype.h>
#include <string.h>

enum TokenType {
  POD_BLOCK,
};

void *tree_sitter_zuzu_external_scanner_create(void) {
  return NULL;
}

void tree_sitter_zuzu_external_scanner_destroy(void *payload) {
  (void)payload;
}

unsigned tree_sitter_zuzu_external_scanner_serialize(void *payload, char *buffer) {
  (void)payload;
  (void)buffer;
  return 0;
}

void tree_sitter_zuzu_external_scanner_deserialize(
  void *payload,
  const char *buffer,
  unsigned length
) {
  (void)payload;
  (void)buffer;
  (void)length;
}

static void advance(TSLexer *lexer) {
  lexer->advance(lexer, false);
}

static bool consume_word(TSLexer *lexer, const char *word) {
  for (size_t i = 0; word[i] != '\0'; i++) {
    if (lexer->lookahead != word[i]) {
      return false;
    }
    advance(lexer);
  }

  return true;
}

bool tree_sitter_zuzu_external_scanner_scan(
  void *payload,
  TSLexer *lexer,
  const bool *valid_symbols
) {
  (void)payload;

  if (!valid_symbols[POD_BLOCK]) {
    return false;
  }

  while (isspace(lexer->lookahead)) {
    advance(lexer);
  }

  if (lexer->get_column(lexer) != 0 || lexer->lookahead != '=') {
    return false;
  }

  advance(lexer);

  bool at_line_start = false;
  bool just_saw_equals_at_line_start = true;

  while (!lexer->eof(lexer)) {
    if (just_saw_equals_at_line_start) {
      if (consume_word(lexer, "cut")) {
        while (!lexer->eof(lexer) && lexer->lookahead != '\n') {
          advance(lexer);
        }
        if (lexer->lookahead == '\n') {
          advance(lexer);
        }
        lexer->result_symbol = POD_BLOCK;
        lexer->mark_end(lexer);
        return true;
      }
      just_saw_equals_at_line_start = false;
    }

    if (lexer->lookahead == '\n') {
      advance(lexer);
      at_line_start = true;
      continue;
    }

    if (at_line_start && lexer->lookahead == '=') {
      advance(lexer);
      at_line_start = false;
      just_saw_equals_at_line_start = true;
      continue;
    }

    advance(lexer);
    at_line_start = false;
  }

  lexer->result_symbol = POD_BLOCK;
  lexer->mark_end(lexer);
  return true;
}
