package day15

import (
	_ "adventofcode2024/utils"
	_ "adventofcode2024/utils/grid2d"
	_ "adventofcode2024/utils/grid2d"
	"adventofcode2024/utils/inputs"
	"fmt"
	_ "regexp"
	"strings"

	_ "github.com/deckarep/golang-set/v2"
)

type Loc struct {
	x int
	y int
}

type Queue struct {
	elements []Loc
}

// Push adds an element to the end of the queue
func (q *Queue) Push(value Loc) {
	q.elements = append(q.elements, value)
}

// Pop removes an element from the front of the queue
func (q *Queue) Pop() (Loc, bool) {
	if len(q.elements) == 0 {
		return Loc{}, false // Return zero and false if the queue is empty
	}
	value := q.elements[0]
	q.elements = q.elements[1:] // Remove the first element
	return value, true
}

// IsEmpty checks if the queue is empty
func (q *Queue) IsEmpty() bool {
	return len(q.elements) == 0
}

func Part1(input string) int {
	var val int
	var rloc Loc
	in := strings.Split(input, "\n\n")
	dirs := map[rune][2]int{
		'<': {-1, 0},
		'>': {1, 0},
		'^': {0, -1},
		'v': {0, 1},
	}
	grid := inputs.ToGrid2D(in[0], "\n", "", ',', func(c string) rune { return rune(c[0]) })
	directions := strings.ReplaceAll(in[1], "\n", "")
	fmt.Printf("%v\n", grid.StringWithFormatter(formatter))
	fmt.Printf("%v\n", directions)
	found := false
	for x := 0; x < grid.SizeX(); x++ {
		if found {
			break
		}
		for y := 0; y < grid.SizeY(); y++ {
			if grid.Get(x, y) == '@' {
				rloc = Loc{x: x, y: y}
				found = true
				break
			}
		}
	}
	fmt.Printf("Robot: %v\n", rloc)
	for _, dir := range directions {
		q := &Queue{}
		x := rloc.x
		y := rloc.y
	Loop:
		for {
			x += dirs[dir][0]
			y += dirs[dir][1]
			switch grid.Get(x, y) {
			case 'O':
				q.Push(Loc{x: x, y: y})
			case '.':
				for !q.IsEmpty() {
					grid.Set(x, y, 'O')
					loc, _ := q.Pop()
					fmt.Printf("%d,%d\n", loc.x, loc.y)
					//					grid.Set(loc.x, loc.y, 'O')
					x -= dirs[dir][0]
					y -= dirs[dir][1]
				}
				grid.Set(rloc.x, rloc.y, '.')
				rloc.x = x
				rloc.y = y
				grid.Set(rloc.x, rloc.y, '@')
				break Loop
			case '#':
				break Loop
			}
		}
		//		fmt.Printf("%v\n", grid.StringWithFormatter(formatter))
	}
	for x := 0; x < grid.SizeX(); x++ {
		for y := 0; y < grid.SizeY(); y++ {
			if grid.Get(x, y) == 'O' {
				val += (100 * y) + x
			}
		}
	}
	return val
}

func Part2(input string) int {
	return 0
}

func formatter(p rune, x int, y int) string {
	return string(p)
}
