package main

import (
	"fmt"
	"log"
	"os"
	"strconv"

	"git.annabunch.es/annabunches/adventofcode/2020/lib/util"
)

func distance(x1, y1, x2, y2 int) int {
	dy := y2 - y1
	dx := x2 - x1
	if dy < 0 {
		dy *= -1
	}
	if dx < 0 {
		dx *= -1
	}
	return dx + dy
}

func rotate(x, y int, direction byte, degrees int) (int, int) {
	turns := degrees / 90

	newX := x
	newY := y

	for i := 0; i < turns; i++ {
		hold := newX
		newX = newY
		newY = hold

		switch direction {
		case 'L':
			newX *= -1
		case 'R':
			newY *= -1
		}
	}

	return newX, newY
}

func step1(values []string) (int, int) {
	facing := 90
	x := 0
	y := 0

	for _, line := range values {
		direction := line[0]
		value, err := strconv.Atoi(line[1:])
		if err != nil {
			log.Panicf(err.Error())
		}
		switch direction {
		case 'N':
			y += value
		case 'S':
			y -= value
		case 'E':
			x += value
		case 'W':
			x -= value
		case 'L':
			facing -= value
		case 'R':
			facing += value
		case 'F':
			// the hard one
			switch facing {
			case 0:
				y += value
			case 90:
				x += value
			case 180:
				y -= value
			case 270:
				x -= value
			default:
				log.Panicf("Oh no, ships can't face %d degrees!", facing)
			}
		}

		if facing < 0 {
			facing += 360
		}

		if facing >= 360 {
			facing %= 360
		}
	}

	return x, y
}

func step2(values []string) (int, int) {
	x := 0
	y := 0
	wayX := 10
	wayY := 1

	for _, line := range values {
		direction := line[0]
		value, err := strconv.Atoi(line[1:])
		if err != nil {
			log.Panicf(err.Error())
		}
		switch direction {
		case 'N':
			wayY += value
		case 'S':
			wayY -= value
		case 'E':
			wayX += value
		case 'W':
			wayX -= value
		case 'L':
			wayX, wayY = rotate(wayX, wayY, direction, value)
		case 'R':
			wayX, wayY = rotate(wayX, wayY, direction, value)
		case 'F':
			for i := 0; i < value; i++ {
				x += wayX
				y += wayY
			}
		}
	}

	return x, y
}

func main() {
	step := os.Args[1]
	values := util.InputParserStrings(os.Args[2])

	x := 0
	y := 0
	switch step {
	case "1":
		x, y = step1(values)
	case "2":
		x, y = step2(values)
	}

	fmt.Println(distance(x, y, 0, 0))
}