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

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

enum Direction { UP, LEFT, RIGHT, DOWN };

typedef struct Position {
  int x;
  int y;
} Position;

typedef struct Map {
  char *data;
  int width;
  int height;
  Position robot;
} Map;

char char_at_position(Map *map, Position p) {
  return map->data[p.x + (map->width * p.y)];
}

void set_char_at_position(Map *map, Position p, char c) {
  map->data[p.x + (map->width * p.y)] = c;
}

bool move(Map *map, Position p, char dir) {
  Position target;
  switch (dir) {
  case '^':
    target.x = p.x;
    target.y = p.y - 1;
    break;
  case '<':
    target.x = p.x - 1;
    target.y = p.y;
    break;
  case '>':
    target.x = p.x + 1;
    target.y = p.y;
    break;
  case 'v':
    target.x = p.x;
    target.y = p.y + 1;
    break;
  }
  // printf("Moving from [%d,%d] to [%d,%d]\n", p.x, p.y, target.x, target.y);
  bool can_move;
  switch (char_at_position(map, target)) {
  case '#':
    can_move = false;
    break;
  case '.':
    can_move = true;
    break;
  case 'O':
    can_move = move(map, target, dir);
    break;
  }

  if (can_move) {
    char mover = char_at_position(map, p);
    if (mover == '@') {
      map->robot.x = target.x;
      map->robot.y = target.y;
    }
    set_char_at_position(map, target, mover);
    set_char_at_position(map, p, '.');
  }

  return can_move;
}

void execute_instruction(Map *m, char inst) {
  if (inst == '\n') return;

  move(m, m->robot, inst);
}

int main() {
  char *input = aoc_read_input();
  char *split = strstr(input, "\n\n");
  split[1] = '\0';
  char *instructions = split + 2;
  int instructions_length = strlen(instructions);

  int robot_index = strchr(input, '@') - input;

  Map m;
  m.data = input;
  m.width = strchr(input, '\n') - input + 1;
  m.height = strlen(input) / m.width;
  m.robot.x = robot_index % m.width;
  m.robot.y = robot_index / m.width;

  for (int i = 0; i < instructions_length; i++) {
    execute_instruction(&m, instructions[i]);
  }

  Position p;
  int total = 0;
  for (int i = 0; i < strlen(input); i++) {
    p.x = i % m.width;
    p.y = i / m.width;
    if (char_at_position(&m, p) == 'O') total += ((100 * p.y) + p.x);
  }

  printf("Part 1: %d\n", total);

  aoc_free();
  exit(0);
}