"""
Advent of Code 2021 - Day 11

Run with:
    python puzzles/day11.py inputs/day11.txt
"""

import pathlib
import sys
from typing import List, Tuple

from dataclasses import dataclass



class School:
    octopi = None
    step = 1

    def __init__(self, data):
        self.parse(data)

    def flash(self, octopus):
        octopus.energy_level = 0
        octopus.flash_count += 1
        octopus.last_flash = self.step
        self.update_neighbors(octopus.location)

    def update(self, octopus):
        if octopus.last_flash == self.step:
            return False

        octopus.energy_level += 1
        if octopus.energy_level == 10:
            self.flash(octopus)

    def update_neighbors(self, location):
        min_row = 0 if location[0] == 0 else location[0] - 1
        min_col = 0 if location[1] == 0 else location[1] - 1
        max_row = location[0] if location[0] == self.size["rows"] - 1 else location[0] + 1
        max_col = location[1] if location[1] == self.size["cols"] - 1 else location[1] + 1

        for row in range(min_row, max_row + 1):
            for col in range(min_col, max_col + 1):
                if row == location[0] and col == location[1]:
                    continue
                if self.octopi[row][col].last_flash == self.step:
                    continue

                self.update(self.octopi[row][col])

    def simulate(self, steps=100):
        for step in range(1, steps+1):
            self.step = step
            for row in self.octopi:
                for octopus in row:
                    self.update(octopus)

    @property
    def total_flashes(self):
        total = 0
        for row in self.octopi:
            for octopus in row:
                total += octopus.flash_count

        return total

    def parse(self, data):
        self.octopi = []
        for row_index, row in enumerate(data):
            self.octopi.append(
                [
                    Octopus(
                        energy_level=int(value),
                        location=(int(row_index), int(column_index)),   # row, col
                    )
                    for column_index, value in enumerate(row)
                ]
            )
        self.size = {"rows": len(self.octopi), "cols": len(self.octopi[0])}


@dataclass
class Octopus:
    energy_level: int = 0
    flash_count: int = 0
    location: Tuple[int, int] = (0, 0)
    last_flash: int = 0


def part1(inputs: List[int]) -> int:
    s = School(inputs)
    s.simulate()
    return s.total_flashes


def part2(inpus: List[int]) -> int:
    return False


def parse(inputs: str) -> List[int]:
    """Parse the input string"""
    return [line for line in inputs.split()]


def solve(path: str) -> Tuple[int, int]:
    """Solve the puzzle"""
    puzzle_input = parse(pathlib.Path(path).read_text().strip())
    part1_result = part1(puzzle_input)
    part2_result = part2(puzzle_input)

    return part1_result, part2_result


def main() -> None:
    for path in sys.argv[1:]:
        print(f"Input File: {path}")

        part1_result, part2_result = solve(path)

        print(f"Part 1 Result: {part1_result}")
        print(f"Part 2 Result: {part2_result}")


if __name__ == "__main__":
    main()