package main

import (
	"fmt"

	h "git.bullercodeworks.com/brian/adventofcode/helpers"
)

func main() {
	inp := h.StdinToStringSlice()
	part1(h.StringSliceToCoordByteMap(inp))
	part2(h.StringSliceToCoordByteMap(inp))
}

func part1(m h.CoordByteMap) {
	var count int
	for i := 0; i < 100; i++ {
		var wrk int
		m, wrk = step(m)
		count += wrk
	}
	fmt.Println("# Part 1")
	fmt.Println("Total Flashes", count)
}

func part2(m h.CoordByteMap) {
	var count int
	var steps int
	for count != len(m.Field) {
		if steps%1000 == 0 {
			fmt.Print("O")
		} else if steps%100 == 0 {
			fmt.Print("o")
		} else if steps%10 == 0 {
			fmt.Print(".")
		}
		m, count = step(m)
		steps++
	}
	fmt.Println()
	fmt.Println("# Part 2")
	fmt.Println("Synchronized after", steps, "steps")
}

func step(m h.CoordByteMap) (h.CoordByteMap, int) {
	var flashes []h.Coordinate
	for y := 0; y < m.Height; y++ {
		for x := 0; x < m.Width; x++ {
			c := h.Coordinate{X: x, Y: y}
			v := m.Get(c)
			switch v {
			case 0:
				continue
			case '9':
				m.Put(c, '.')
				flashes = append(flashes, c)
			default:
				m.Put(c, v+1)
			}
		}
	}
	for len(flashes) > 0 {
		var next []h.Coordinate
		for i := range flashes {
			var wrk []h.Coordinate
			m, wrk = flash(flashes[i], m)
			next = append(next, wrk...)
		}
		flashes = next
	}
	var flashCount int
	for y := 0; y < m.Height; y++ {
		for x := 0; x < m.Width; x++ {
			c := h.Coordinate{X: x, Y: y}
			if m.Get(c) == 'o' {
				m.Put(c, '0')
				flashCount++
			}
		}
	}
	return m, flashCount
}

func flash(c h.Coordinate, m h.CoordByteMap) (h.CoordByteMap, []h.Coordinate) {
	var flashes []h.Coordinate
	m.Put(c, 'o')
	for _, n := range []h.Coordinate{c.North(), c.NE(), c.East(), c.SE(), c.South(), c.SW(), c.West(), c.NW()} {
		v := m.Get(n)
		switch v {
		case 0, '.', 'o':
			continue
		case '9':
			m.Put(n, '.')
			flashes = append(flashes, n)
		default:
			m.Put(n, v+1)
		}
		if v == 0 {
			continue
		}
	}
	return m, flashes
}
