package day02

import (
	"adventofcode2024/utils"
	_ "adventofcode2024/utils"
	_ "adventofcode2024/utils/grid2d"
	_ "adventofcode2024/utils/inputs"
	_ "errors"
	_ "fmt"
	"strings"
)

type Dir int

const (
    Up Dir = iota
    Down
    Safe
	Unsafe
)

// Implement the Stringer interface
func (d Dir) String() string {
    switch d {
    case Up:
        return "Up"
    case Down:
        return "Down"
    case Safe:
        return "Safe"
	case Unsafe:
        return "Unsafe"
	default:
		return "Unknown"
    }
}

func Part1(input string) int {
	count := 0
	lines := strings.Split(input, "\n")
	for _, line := range lines {
		fields := strings.Fields(line)
		if isSafe(fields) {count++}
	}
	return count
}

func Part2(input string) int {
	count := 0
	lines := strings.Split(input, "\n")
	for _, line := range lines {
		fields := strings.Fields(line)
		if isSafe(fields) {
			count++
		} else {
			for i := 0; i < len(fields); i++ {
				// Create a new slice excluding the current item
				newFields := applyDampner(fields, i)
				if isSafe(newFields) {
					count++
					break
				}
			}
		}
	}
	return count
}

func isSafe(fields []string) bool {
	Dir := getDir(utils.MustAtoi(fields[0]), utils.MustAtoi(fields[1]))
	if Dir == Unsafe {
			return false
	}
	for x := 2; x < len(fields); x++ {
		NextDir := getDir(utils.MustAtoi(fields[x-1]), utils.MustAtoi(fields[x]))
		if NextDir == Unsafe {
			return false
		}
		if NextDir != Dir {
			return false
		}
	}
	return true
}

func getDir(a int, b int) Dir {
	var dir Dir
	diff := b - a
	if diff > 0 && utils.Abs(diff) < 4 {
		dir = Up
	} else if diff < 0 && utils.Abs(diff) < 4 {
		dir = Down
	} else {
		dir = Unsafe
	}
	return dir
}

func applyDampner(fields []string, pos int) []string {
	copy := append([]string{}, fields...)
    if pos < 0 || pos >= len(copy) {
        return copy // Return the fields unchanged if pos is invalid
    }
    return append(copy[:pos], copy[pos+1:]...)
}