#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>

#include "../../lib/aoc.h"

char *target_string = "XMAS";
#define TARGET_STRING_LENGTH 4

typedef struct Puzzle {
  char *text;
  int width;
  int height;
} Puzzle;

char puzzle_char_at(Puzzle *puzzle, int row, int column) {
  return puzzle->text[column + (puzzle->width * row)];
}

bool puzzle_inbounds(Puzzle *puzzle, int row, int column) {
  return row < puzzle->height && row >= 0 && column >= 0 && column < puzzle->width;
}

int target_string_count(Puzzle *puzzle, int index) {
  if (puzzle->text[index] != target_string[0]) return 0;
  int count = 0;
  int row = index / puzzle->width;
  int column = index % puzzle->width;

  // right
  for (int i = 1; i < TARGET_STRING_LENGTH; i++) {
    if (!puzzle_inbounds(puzzle, row, column + i)) break;
    if (puzzle_char_at(puzzle, row, column + i) != target_string[i]) break;
    if (i == TARGET_STRING_LENGTH - 1) count += 1;
  }

  // down right
  for (int i = 1; i < TARGET_STRING_LENGTH; i++) {
    if (!puzzle_inbounds(puzzle, row + i, column + i)) break;
    if (puzzle_char_at(puzzle, row + i, column + i) != target_string[i]) break;
    if (i == TARGET_STRING_LENGTH - 1) count += 1;
  }

  // down
  for (int i = 1; i < TARGET_STRING_LENGTH; i++) {
    if (!puzzle_inbounds(puzzle, row + i, column)) break;
    if (puzzle_char_at(puzzle, row + i, column) != target_string[i]) break;
    if (i == TARGET_STRING_LENGTH - 1) count += 1;
  }

  // down left
  for (int i = 1; i < TARGET_STRING_LENGTH; i++) {
    if (!puzzle_inbounds(puzzle, row + i, column - i)) break;
    if (puzzle_char_at(puzzle, row + i, column - i) != target_string[i]) break;
    if (i == TARGET_STRING_LENGTH - 1) count += 1;
  }

  // left
  for (int i = 1; i < TARGET_STRING_LENGTH; i++) {
    if (!puzzle_inbounds(puzzle, row, column - i)) break;
    if (puzzle_char_at(puzzle, row, column - i) != target_string[i]) break;
    if (i == TARGET_STRING_LENGTH - 1) count += 1;
  }

  // up left
  for (int i = 1; i < TARGET_STRING_LENGTH; i++) {
    if (!puzzle_inbounds(puzzle, row - i, column - i)) break;
    if (puzzle_char_at(puzzle, row - i, column - i) != target_string[i]) break;
    if (i == TARGET_STRING_LENGTH - 1) count += 1;
  }

  // up
  for (int i = 1; i < TARGET_STRING_LENGTH; i++) {
    if (!puzzle_inbounds(puzzle, row - i, column)) break;
    if (puzzle_char_at(puzzle, row - i, column) != target_string[i]) break;
    if (i == TARGET_STRING_LENGTH - 1) count += 1;
  }

  // up right
  for (int i = 1; i < TARGET_STRING_LENGTH; i++) {
    if (!puzzle_inbounds(puzzle, row - i, column + i)) break;
    if (puzzle_char_at(puzzle, row - i, column + i) != target_string[i]) break;
    if (i == TARGET_STRING_LENGTH - 1) count += 1;
  }

  return count;
}

char mas[4];
int xmas_count(Puzzle *puzzle, int index) {
  if (puzzle->text[index] != 'A') return 0;
  int count = 0;
  int row = index / puzzle->width;
  int column = index % puzzle->width;
  if (
      puzzle_inbounds(puzzle, row - 1, column + 1) &&
      puzzle_inbounds(puzzle, row + 1, column + 1) &&
      puzzle_inbounds(puzzle, row + 1, column - 1) &&
      puzzle_inbounds(puzzle, row - 1, column - 1)
      ) {
    mas[0] = puzzle_char_at(puzzle, row - 1, column + 1);
    mas[1] = puzzle_char_at(puzzle, row + 1, column + 1);
    mas[2] = puzzle_char_at(puzzle, row + 1, column - 1);
    mas[3] = puzzle_char_at(puzzle, row - 1, column - 1);
    if (((mas[0] == 'M' && mas[2] == 'S') || (mas[0] == 'S' && mas[2] == 'M')) &&
	((mas[1] == 'M' && mas[3] == 'S') || (mas[1] == 'S' && mas[3] == 'M'))) {
      return 1;
    }
  }
  return 0;
}

int main() {
  char *input = aoc_read_input();
  int width = strchr(input, '\n') - input + 1;
  int height = strlen(input) / width;

  Puzzle p;
  p.text = input;
  p.width = width;
  p.height = height;

  int sum = 0;
  int xmas_sum = 0;

  for (int i = 0; i < strlen(input); i++) {
    sum += target_string_count(&p, i);
    xmas_sum += xmas_count(&p, i);
  }

  printf("Part 1: %d\n", sum);
  printf("Part 2: %d\n", xmas_sum);

  aoc_free();
  return 0;
}