package day08

import (
	"math"
	"strings"
)

type Coordinate struct {
	Row int
	Col int
}

func Part1(input string) int {
	grid, antennaMap := parseInput(input)
	result := findAntinodes(grid, antennaMap, true)
	return result
}

func Part2(input string) int {
	grid, antennaMap := parseInput(input)
	result := findAntinodes(grid, antennaMap, false)
	return result
}

func parseInput(input string) ([][]rune, map[rune][]Coordinate) {
	lines := strings.Split(input, "\n")
	rowCount := len(lines)
	colCount := len(lines[0])
	grid := make([][]rune, rowCount)
	antennaMap := make(map[rune][]Coordinate)

	for row := 0; row < rowCount; row++ {
		grid[row] = []rune(lines[row])
		for col := 0; col < colCount; col++ {
			frequency := grid[row][col]
			if frequency != '.' {
				antennaMap[frequency] = append(antennaMap[frequency], Coordinate{Row: row, Col: col})
			}
		}
	}

	return grid, antennaMap
}

func findAntinodes(grid [][]rune, antennaMap map[rune][]Coordinate, onlySpecial bool) int {
	rowCount := len(grid)
	colCount := len(grid[0])
	uniqueAntinodes := make(map[Coordinate]struct{})

	for row := 0; row < rowCount; row++ {
		for col := 0; col < colCount; col++ {
			for _, antennaPositions := range antennaMap {
				for i, firstAntenna := range antennaPositions {
					for j, secondAntenna := range antennaPositions {
						//I know I know thats too many for loops
						if i != j {
							distance1 := int(math.Abs(float64(row-firstAntenna.Row)) + math.Abs(float64(col-firstAntenna.Col)))
							distance2 := int(math.Abs(float64(row-secondAntenna.Row)) + math.Abs(float64(col-secondAntenna.Col)))

							rowDiff1 := row - firstAntenna.Row
							rowDiff2 := row - secondAntenna.Row
							colDiff1 := col - firstAntenna.Col
							colDiff2 := col - secondAntenna.Col

							if rowDiff1*colDiff2 == rowDiff2*colDiff1 {
								if (distance1 == 2*distance2 || distance1*2 == distance2) && onlySpecial {
									uniqueAntinodes[Coordinate{Row: row, Col: col}] = struct{}{}
								} else if !onlySpecial {
									uniqueAntinodes[Coordinate{Row: row, Col: col}] = struct{}{}
								}
							}
						}
					}
				}
			}
		}
	}

	return len(uniqueAntinodes)
}
