package main

import (
	"fmt"
	"os"
	"strings"

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

func main() {
	fmt.Println("vim-go")
	inp := h.StdinToStringSlice()
	part1(inp)
}

func part1(inp []string) {
	scanners := parseScanners(inp)
	m, l := matchScanners(scanners)
	fmt.Println(m)
	fmt.Println(l)
}

func parseScanners(inp []string) []Scanner {
	var scanners []Scanner
	for i := range inp {
		if strings.HasPrefix(inp[i], "---") {
			// Find the next empty line
			end := i
			for ; end < len(inp); end++ {
				if inp[end] == "" {
					break
				}
			}
			// a new scanner
			wrk, err := NewScannerFromInput(inp[i:end])
			if err == nil {
				scanners = append(scanners, wrk)
			} else {
				fmt.Println("Error parsing scanners")
				os.Exit(1)
			}
		}
	}
	return scanners
}

type Match struct {
	beacon   Beacon
	rotation int
}

func matchScanners(scanners []Scanner) (map[Pair]Match, []int) {
	matched := make(map[Pair]Match)
	newMatch := []int{0}
	remaining := make(map[int]bool)
	for i := 1; i < len(scanners); i++ {
		remaining[i] = true
	}
	prev := make([]int, len(scanners))
	for len(remaining) > 0 {
		fmt.Println("Remaining:", len(remaining))
		next := []int{}
		for _, mID := range newMatch {
			fmt.Println("  Working", mID)
			for uID := range remaining {
				fmt.Println("  ->", uID)
				if _, ok := matched[Pair{mID, uID}]; ok {
					continue
				}
				for _, finger := range scanners[mID].prints {
					for _, fWrk := range scanners[uID].prints {
						if finger.area == fWrk.area && finger.circumference == fWrk.circumference {
							// Found a matching print in both scanners, figure out orientation
							tx := findTranslations(finger, fWrk)
							fmt.Println("Translations:", tx)
							//fb, fRotID := findTranslation(finger, fWrk)
							for k, v := range tx {
								if len(v) >= 3 {
									fmt.Println("Found:", v)
									prev[uID] = mID
									matched[Pair{mID, uID}] = Match{k, v[0].rotID}
									next = append(next, uID)
									delete(remaining, uID)
									break
								}
							}
						}
					}
				}
			}
		}
		newMatch = next
	}
	return matched, prev
}

func findTranslations(f1, f2 Triangle) map[Beacon][]Translation {
	//func findTranslation(f1, f2 Triangle) (Beacon, int) {
	tx := make(map[Beacon][]Translation)
	for rID := 0; rID < 24; rID++ {
		for oIdx, orig := range []Beacon{f1.a, f1.b, f1.c} {
			for fIdx, foreign := range []Beacon{f2.a, f2.b, f2.c} {
				diff := foreign.Rotate(rID).Sub(orig)
				t := Translation{oIdx, fIdx, rID}
				if v, ok := tx[diff]; ok {
					v = append(v, t)
					tx[diff] = v
				} else {
					tx[diff] = []Translation{t}
				}
			}
		}
		for _, v := range tx {
			// If we find 3, we have a match
			if len(v) >= 3 {
				return tx
			}
		}
	}
	return tx
}
