package main

import (
	"AOC2021/src/helper"
	"fmt"
	"os"
	"strings"
)

type point struct {
	x int
	y int
}

func main() {
	args := os.Args[1:]
	input, err := helper.GetInput(args[0])
	if err != nil {
		fmt.Println(err)
	}
	lines, maxY, maxX := parseInput(input)
	calculateSolution(maxY, maxX, lines,false)
	calculateSolution(maxY, maxX, lines,true)

}

func calculateSolution(maxY int, maxX int, lines [][2]point, part2 bool) {
	field := make([][]int, maxY+1)
	for i, _ := range field {
		field[i] = make([]int, maxX+1)
	}
	for _, line := range lines {
		drawLine(&field, line, part2)
	}
	fmt.Println(findOverlaps(field))
}

func parseInput(input []string) ([][2]point, int, int) {
	lines := make([][2]point, len(input))
	maxY := 0
	maxX := 0
	for i, row := range input {
		points := strings.Split(row, " -> ")
		for j, p := range points {
			coordinatesStrings := strings.Split(p, ",")
			coordinatesInt, _ := helper.MapToNumber(coordinatesStrings)
			lines[i][j] = point{coordinatesInt[0], coordinatesInt[1]}
			if coordinatesInt[0] > maxX {
				maxX = coordinatesInt[0]
			}
			if coordinatesInt[1] > maxY {
				maxY = coordinatesInt[1]
			}
		}
	}
	return lines, maxY, maxX
}

func drawLine(field* [][]int, line [2]point, part2 bool){
	slope := getSlope(line)
	if !part2 && slope.y != 0 && slope.x != 0 {
		return
	}
	i := line[0].x
	j := line[0].y
	for {
		(*field)[j][i] += 1
		if i == line[1].x && j == line[1].y {
			break
		}
		i += slope.x
		j += slope.y
	}
}

func getSlope(line [2]point) point {
	x := line[1].x - line[0].x
	y := line[1].y - line[0].y
	if x == 0 {
		return point{x,y / helper.Abs(y)}
	}
	if y == 0 {
		return point{x / helper.Abs(x), y}
	}

	gcd := helper.GCD(helper.Abs(x), helper.Abs(y))
	return point{x / gcd,y / gcd}
}

func printField(field [][]int)  {
	for _,row := range field {
		fmt.Println(row)
	}
}

func findOverlaps(field [][]int) int{
	sum := 0
	for _, row := range field {
		for _, p := range row {
			if p > 1 {
				sum += 1
			}
		}
	}
	return sum
}
