package main

import "core:log"
import "core:os"
import "core:slice"
import "core:strings"

Input :: struct {
	grid: [][]u8,
}

Result1 :: distinct int
Result2 :: distinct int


// --- Input --- //
print_input :: proc(input: ^Input) {
	for line in input.grid {
		log.infof("%s", line)
	}
}

parse_input_file :: proc(filepath: string) -> Input {
	input: Input

	raw_data, ok := os.read_entire_file_from_filename(filepath)
	if !ok {
		panic("oh no, could not read file")
	}
	defer delete(raw_data)

	lines := strings.split_lines(string(raw_data))
	defer delete(lines)

	input.grid = make([][]u8, len(lines) - 1)
	i: int
	for line in lines {
		if len(line) == 0 {
			continue
		}
		input.grid[i] = slice.clone(transmute([]u8)line[:])
		i += 1
	}

	return input
}

free_input :: proc(input: ^Input) {
	for _, i in input.grid {
		delete(input.grid[i])
	}
	delete(input.grid)
}
// --- Input --- //


// --- Helpers --- //
Direction :: enum {
	Up,
	Down,
	Left,
	Right,
	UpLeft,
	UpRight,
	DownLeft,
	DownRight,
}

print_grid :: proc(grid: [][]u8) {
	for line in grid {
		log.debugf("%s", line)
	}
}
// --- Helpers --- //


// --- Task 1 --- //
run_task1 :: proc(input: ^Input, debug: bool) -> Result1 {
	result: Result1

	if debug {
		print_input(input)
	}

	grid := make([][]u8, len(input.grid))
	for _, i in grid {
		grid[i] = make([]u8, len(input.grid[i]))
	}
	defer {
		for _, i in grid {
			delete(grid[i])
		}
		delete(grid)
	}

	chars := []u8{'X', 'M', 'A', 'S'}
	height := len(grid)
	for y in 0 ..< height {
		width := len(grid[y])
		for x in 0 ..< width {
			if input.grid[y][x] != 'X' {
				grid[y][x] = '.'
				continue
			}

			matches: [Direction]int
			for c, i in chars {
				if y - i >= 0 {
					if c == input.grid[y - i][x] {
						matches[.Up] += 1
					}
				}
				if y + i < height {
					if c == input.grid[y + i][x] {
						matches[.Down] += 1
					}
				}
				if x - i >= 0 {
					if c == input.grid[y][x - i] {
						matches[.Left] += 1
					}
				}
				if x + i < width {
					if c == input.grid[y][x + i] {
						matches[.Right] += 1
					}
				}
				if y - i >= 0 && x - i >= 0 {
					if c == input.grid[y - i][x - i] {
						matches[.UpLeft] += 1
					}
				}
				if y - i >= 0 && x + i < width {
					if c == input.grid[y - i][x + i] {
						matches[.UpRight] += 1
					}
				}
				if y + i < height && x - i >= 0 {
					if c == input.grid[y + i][x - i] {
						matches[.DownLeft] += 1
					}
				}
				if y + i < height && x + i < width {
					if c == input.grid[y + i][x + i] {
						matches[.DownRight] += 1
					}
				}
			}

			log.debugf("%v", matches)

			grid[y][x] = 'F'
			for m in matches {
				if m == len(chars) {
					grid[y][x] = 'T'
					result += 1
				}
			}
		}
	}

	print_grid(grid)

	return result
}

print_result1 :: proc(result: ^Result1) {
	log.infof("Task 1: %d", result^)
}
// --- Task 1 --- //


// --- Task 2 --- //
run_task2 :: proc(input: ^Input, debug: bool) -> Result2 {
	result: Result2

	if debug {
		print_input(input)
	}

	grid := make([][]u8, len(input.grid))
	for _, i in grid {
		grid[i] = make([]u8, len(input.grid[i]))
	}
	defer {
		for _, i in grid {
			delete(grid[i])
		}
		delete(grid)
	}

	height := len(grid)
	for y in 1 ..< height - 1 {
		width := len(grid[y])
		for x in 1 ..< width - 1 {
			if input.grid[y][x] != 'A' {
				grid[y][x] = ' '
				continue
			}

			matches: int
			if 'M' == input.grid[y - 1][x - 1] && 'S' == input.grid[y + 1][x + 1] {
				matches += 1
			}
			if 'S' == input.grid[y - 1][x - 1] && 'M' == input.grid[y + 1][x + 1] {
				matches += 1
			}
			if 'M' == input.grid[y + 1][x - 1] && 'S' == input.grid[y - 1][x + 1] {
				matches += 1
			}
			if 'S' == input.grid[y + 1][x - 1] && 'M' == input.grid[y - 1][x + 1] {
				matches += 1
			}

			grid[y][x] = 'T' if matches == 2 else 'F'
			if matches == 2 {
				result += 1
			}
		}
	}

	print_grid(grid)

	return result
}

print_result2 :: proc(result: ^Result2) {
	log.infof("Task 2: %d", result^)
}
// --- Task 2 --- //