"""
Advent of Code 2021 - Day 07

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

import pathlib
import sys
from statistics import median
from typing import List, Tuple


class AlignCrabSubs:
    positions: List[int]

    def __init__(self, positions: List[int]) -> None:
        self.positions = positions

    def calc_fuel(self, pricey: bool = False) -> int:
        if not pricey:
            return self.calc_fuel_simple(median(self.positions))

        fuel = None
        for position in range(len(set(self.positions)) + 1):
            price = self.calc_fuel_pricey(position)
            if fuel is None or fuel > price:
                fuel = price

        return fuel

    def calc_fuel_simple(self, target: int) -> int:
        return int(sum(abs(num - target) for num in self.positions))

    def calc_fuel_pricey(self, target: int) -> int:
        # This is slow and needs reworking
        fuel = 0
        for num in self.positions:
            num_range = abs(num - target) + 1
            fuel += sum(range(num_range))
        return int(fuel)


def part1(inputs: List[int]) -> int:
    subs = AlignCrabSubs(inputs)
    return subs.calc_fuel()


def part2(inputs: List[int]) -> int:
    subs = AlignCrabSubs(inputs)
    return subs.calc_fuel(pricey=True)


def parse(inputs: str) -> List[int]:
    """Parse the input string"""
    return [int(value) for value 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()