package day_05

import "core:log"
import "core:os"
import "core:strconv"
import "core:strings"

Input :: struct {
	fresh_ranges: [][2]int,
	ingredients:  []int,
}

Result1 :: int
Result2 :: int

// --- Input --- //
print_input :: proc(input: Input) {
	log.infof("%#v", input)
}

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)

	split := 0
	for line, i in lines {
		if line == "" {
			split = i
			break
		}
	}

	input.fresh_ranges = make([][2]int, split)
	input.ingredients = make([]int, len(lines) - split - 1)

	for line, i in lines[:split] {
		range := strings.split(line, "-")
		defer delete(range)

		a := strconv.parse_int(range[0]) or_else 0
		b := strconv.parse_int(range[1]) or_else 0
		input.fresh_ranges[i] = {a, b}
	}

	for line, i in lines[split + 1:] {
		input.ingredients[i] = strconv.parse_int(line) or_else 0
	}

	log.debugf("%d %d", len(input.ingredients), len(input.fresh_ranges))
	log.debugf("%#v", input)

	return input
}

free_input :: proc(input: ^Input) {
	delete(input.fresh_ranges)
	delete(input.ingredients)
}
// --- Input --- //


// --- Helpers --- //
// --- Helpers --- //


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

	for i in input.ingredients {
		for fr in input.fresh_ranges {
			if i >= fr[0] && i <= fr[1] {
				result += 1
				break
			}
		}
	}

	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

	ranges := input.fresh_ranges
	current_ranges := make([][2]int, len(ranges))
	defer delete(current_ranges)
	expanded := true
	for expanded {
		expanded = false

		for i := 0; i < len(ranges); i += 1 {
			current := ranges[i]
			if current == {0, 0} {
				continue
			}
			for j := i + 1; j < len(ranges); j += 1 {
				range := ranges[j]
				if range == {0, 0} {
					continue
				}
				if current[0] <= range[1] && range[0] <= current[1] {
					current[0] = min(current[0], range[0])
					current[1] = max(current[1], range[1])
					expanded = true
					ranges[j] = {0, 0}
				}
			}
			current_ranges[i] = current
		}

		ranges = current_ranges
		log.debugf("%v -> %v", ranges, current_ranges)
	}

	log.debugf("final ranges %#v", ranges)
	for r in ranges {
		if r == {0, 0} {
			continue
		}
		result += (r[1] - r[0]) + 1
	}

	return result
}

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

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

	result1 := run_task1(input)
	print_result1(result1)

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