package day_04

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

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

Result1 :: int
Result2 :: int

// --- Input --- //
print_input :: proc(input: Input) {
	offset := 0
	for _ in 0 ..< input.width {
		log.infof("%v", string(input.grid[offset:offset + input.width]))
		offset += input.width
	}
}

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, err := strings.split_lines(strings.trim_right_space(string(raw_data)))
	if err != .None {
		panic("oh no, failed splitting into lines")
	}
	defer delete(lines)

	input.width = len(lines[0])
	input.grid = make([]u8, input.width * input.width)

	offset := 0
	for line in lines {
		for c in line {
			input.grid[offset] = u8(c)
			offset += 1
		}
	}

	return input
}

free_input :: proc(input: ^Input) {
	delete(input.grid)
	input.grid = nil
}
// --- Input --- //


// --- Helpers --- //
print_grid :: proc(grid: []u8, width: int) {
	offset := 0
	for _ in 0 ..< width {
		log.debugf("%v", string(grid[offset:offset + width]))
		offset += width
	}
}
// --- Helpers --- //


// --- Task 1 --- //
run_task1 :: proc(input: Input) -> Result1 {
	result: Result1

	ymin, ymax := 0, input.width - 1
	xmin, xmax := 0, input.width - 1

	i := 0
	for y in 0 ..< input.width {
		for x in 0 ..< input.width {
			if input.grid[i] == '@' {

				c: int
				if y > ymin {
					c += 1 if x > xmin && input.grid[i - input.width - 1] == '@' else 0
					c += 1 if input.grid[i - input.width] == '@' else 0
					c += 1 if x < xmax && input.grid[i - input.width + 1] == '@' else 0
				}
				c += 1 if x > xmin && input.grid[i - 1] == '@' else 0
				c += 1 if x < xmax && input.grid[i + 1] == '@' else 0
				if y < ymax {
					c += 1 if x > xmin && input.grid[i + input.width - 1] == '@' else 0
					c += 1 if input.grid[i + input.width] == '@' else 0
					c += 1 if x < xmax && input.grid[i + input.width + 1] == '@' else 0
				}

				if c < 4 {
					result += 1
				}
			}

			i += 1
		}
	}

	return result
}

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


// --- Task 2 --- //
run_task2 :: proc(input: Input) -> Result2 {
	result: Result2

	ymin, ymax := 0, input.width - 1
	xmin, xmax := 0, input.width - 1

	grid_a := slice.clone(input.grid)
	defer delete(grid_a)
	grid_b := slice.clone(input.grid)
	defer delete(grid_b)

	keep_running := true
	for keep_running {
		keep_running = false

		i := 0
		for y in 0 ..< input.width {
			for x in 0 ..< input.width {
				if grid_a[i] == '@' {
					c: int
					if y > ymin {
						c += 1 if x > xmin && grid_a[i - input.width - 1] == '@' else 0
						c += 1 if grid_a[i - input.width] == '@' else 0
						c += 1 if x < xmax && grid_a[i - input.width + 1] == '@' else 0
					}
					c += 1 if x > xmin && grid_a[i - 1] == '@' else 0
					c += 1 if x < xmax && grid_a[i + 1] == '@' else 0
					if y < ymax {
						c += 1 if x > xmin && grid_a[i + input.width - 1] == '@' else 0
						c += 1 if grid_a[i + input.width] == '@' else 0
						c += 1 if x < xmax && grid_a[i + input.width + 1] == '@' else 0
					}

					if c < 4 {
						result += 1
						grid_b[i] = 'x'
						keep_running = true
					} else {
						grid_b[i] = grid_a[i]
					}
				} else {
					grid_b[i] = grid_a[i]
				}

				i += 1
			}
		}

		grid_a, grid_b = grid_b, grid_a
		print_grid(grid_a, input.width)
		log.debugf("---")
	}

	return result
}

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

run :: proc() {
	input := parse_input_file("input/day_04.txt")
	defer free_input(&input)

	result1 := run_task1(input)
	print_result1(result1)

	result2 := run_task2(input)
	print_result2(result2)
}