package main

import (
	"fmt"

	"../../"
)

// pt1 input: 3014387
func main() {
	partOne := aoc.ArgIsSet("-1")
	num := 3014387
	if aoc.ArgIsSet("-test") {
		num = 5 // Example
	}
	firstElf := CreateElf(1)
	t := CreateElf(2)
	firstElf.setLeft(t)
	t.setRight(firstElf)
	fmt.Println("Generating Elves...")
	for i := 3; i <= num; i++ {
		nextElf := CreateElf(i)
		nextElf.setRight(t)
		t.setLeft(nextElf)
		t = nextElf
	}
	t.setLeft(firstElf)
	firstElf.setRight(t)

	fmt.Println(num, "Elves Generated.")
	fmt.Println("Initiating Greed Injection...")

	t = firstElf
	if !partOne {
		t = GetElfAcrossCircle(t, num)
	}
	for t.getLeft() != t {
		if partOne {
			// Remove the elf to the left
			t = t.getLeft()
			t = t.remove()
			num--
		} else {
			// Remove the current elf, the next elf to be removed is the one to the left
			// (remove() returns a pointer to the elf to it's left)
			t = t.remove()
			if num%2 == 1 {
				// Unless we have an odd number of elves, then we skip this one
				t = t.getLeft()
			}
			num--
		}
	}
	fmt.Println("The lucky elf is elf #", t.getId())
}

func GetElfAcrossCircle(e *Elf, num int) *Elf {
	retElf := e
	for i := 0; i < num/2; i++ {
		retElf = retElf.getLeft()
	}
	return retElf
}

type Elf struct {
	id      int
	out     bool
	toRight *Elf
	toLeft  *Elf
}

// To keep the game running smoothly, an elf is required to
// let the gamemaster know who the elf to their left is when they
// are eliminated
func (e *Elf) remove() *Elf {
	e.getLeft().setRight(e.getRight())
	e.getRight().setLeft(e.getLeft())
	return e.getLeft()
}

func (e *Elf) getId() int {
	return e.id
}

func (e *Elf) getRight() *Elf {
	return e.toRight
}

func (e *Elf) setRight(r *Elf) {
	e.toRight = r
}

func (e *Elf) getLeft() *Elf {
	return e.toLeft
}

func (e *Elf) setLeft(l *Elf) {
	e.toLeft = l
}

func CreateElf(id int) *Elf {
	r := new(Elf)
	r.id = id
	return r
}
