#include "_.h"


void display_map(char **map) {
    for (int i = 0; map[i] != NULL; i++)
        printf("%s\n", map[i]);
}

int *pos_robot;

int is_good(char **map, int pos[], int move) {
    int add_x = move == '<' ? -1 : move == '>' ? 1 : 0;
    int add_y = move == '^' ? -1 : move == 'v' ? 1 : 0;
    int new_pos[2] = {pos[0] + add_y, pos[1] + add_x};
    char tile = map[pos[0]][pos[1]];
    char next_tile = map[new_pos[0]][new_pos[1]];

    // check wall
    if (next_tile == '#')
        return 1;
    if (tile == '[')
        if (map[new_pos[0]][new_pos[1] + 1] == '#')
            return 1;
    if (tile == ']')
        if (map[new_pos[0]][new_pos[1] - 1] == '#')
            return 1;

    int left_right = next_tile == ']' ? -1 : next_tile == '[' ? 1 : 0;
    if (left_right != 0) {
        if (is_good(map, new_pos, move) == 1)
            return 1;
        if (add_y != 0) {
            int second_new_pos[2] = {new_pos[0], new_pos[1] + left_right};
            if (is_good(map, second_new_pos, move) == 1)
                return 1;
        }
    }
    return 0;
}

int move_object(char ***map_t, int pos[], int move) {
    char **map = *map_t;

    int add_x = move == '<' ? -1 : move == '>' ? 1 : 0;
    int add_y = move == '^' ? -1 : move == 'v' ? 1 : 0;
    int new_pos[2] = {pos[0] + add_y, pos[1] + add_x};
    char tile = map[pos[0]][pos[1]];
    char next_tile = map[new_pos[0]][new_pos[1]];

    // check wall
    if (next_tile == '#')
        return 1;
    if (tile == '[')
        if (map[new_pos[0]][new_pos[1] + 1] == '#')
            return 1;
    if (tile == ']')
        if (map[new_pos[0]][new_pos[1] - 1] == '#')
            return 1;

    if (is_good(map, pos, move) == 1)
        return 1;

    int left_right = next_tile == ']' ? -1 : next_tile == '[' ? 1 : 0;
    if (left_right != 0) {
        if (move_object(map_t, new_pos, move) == 1)
            return 1;
        if (add_y != 0) {
            int second_new_pos[2] = {new_pos[0], new_pos[1] + left_right};
            if (move_object(map_t, second_new_pos, move) == 1)
                return 1;
        }
    }

    map[new_pos[0]][new_pos[1]] = map[pos[0]][pos[1]];
    map[pos[0]][pos[1]] = '.';

    if (tile == '@') {
        pos_robot[0] = pos[0] + add_y;
        pos_robot[1] = pos[1] + add_x;
    }

    return 0;
}

long sum_boxe(char **map) {
    long sum = 0;

    for (int i = 0; map[i] != NULL; i++)
        for (int j = 0; map[i][j + 1] != '\0'; j++)
            if (map[i][j] == '[' && map[i][j + 1] == ']')
                sum += (100 * i + j);

    return sum;
}

int check (char **map) {
    for (int i = 0; map[i] != NULL; i++)
        for (int j = 0; map[i][j + 1] != '\0'; j++)
            if ((map[i][j] == '[' && map[i][j + 1] != ']') ||
                (map[i][j] == ']' && map[i][j - 1] != '['))
                return 1;
    return 0;
}

int main(int argc, char **argv) {
	
	if (argc != 3)
		return 1;

	char **old_map = str_split(strdup(argv[1]), '\n');
	char **move_map = str_split(strdup(argv[2]), '\n');

    pos_robot = calloc(2, sizeof(int));

    char **map = calloc(strslen(old_map) + 1, sizeof(char *)); 
	for (int i = 0; old_map[i] != NULL; i++) {
        map[i] = calloc(strlen(old_map[i]) * 2 + 1, sizeof(char));
        for (int j = 0; old_map[i][j] != '\0'; j++) {
            if (old_map[i][j] == '#') {
                map[i][j * 2] = '#';
                map[i][j * 2 + 1] = '#';
            }
            if (old_map[i][j] == 'O') {
                map[i][j * 2] = '[';
                map[i][j * 2 + 1] = ']';
            }
            if (old_map[i][j] == '.') {
                map[i][j * 2] = '.';
                map[i][j * 2 + 1] = '.';
            }
            if (old_map[i][j] == '@') {
                pos_robot[0] = i;
                pos_robot[1] = j * 2;
                map[i][j * 2] = '@';
                map[i][j * 2 + 1] = '.';
            }
        }
    }

    for (int i = 0; move_map[i] != NULL; i++)
        for (int j = 0; move_map[i][j] != '\0'; j++)
            move_object(&map, pos_robot, move_map[i][j]);

    //display_map(map);
    long sum = sum_boxe(map);

    printf("sum: %ld\n", sum);

	return 0;
}
