package main

import (
	"bufio"
	"fmt"
	"log"
	"os"
	"strconv"
	"strings"
)

func main() {
	input := stdinToStringSlice()
	var verbose, pt2 bool
	var allDiscs []Disc
	if len(os.Args) > 1 {
		for i := range os.Args {
			switch os.Args[i] {
			case "-2": // Do part 2
				pt2 = true
			case "-v": // Verbose mode
				verbose = true
			}
		}
	}

	for i := range input {
		pts := strings.Fields(input[i])
		id := atoi(pts[1][1:])
		ttl := atoi(pts[3])
		curr := atoi(pts[11][0 : len(pts[11])-1])
		allDiscs = append(allDiscs, *CreateDisc(id, ttl, curr))
	}

	if pt2 {
		d := CreateDisc(7, 11, 0)
		allDiscs = append(allDiscs, *d)
	}

	var numTicks int

	for !AllDiscsAlign(allDiscs) {
		numTicks++
		TickAllDiscs(allDiscs)
		if verbose {
			PrintStatus(allDiscs)
		}
	}
	fmt.Println("Total Ticks: ", numTicks)
}

func PrintStatus(d []Disc) {
	fmt.Print("[ ")
	for i := range d {
		fmt.Printf("(%2d/%2d) ", d[i].currPos, d[i].ttlPos)
	}
	fmt.Println("]")
}

func TickAllDiscs(d []Disc) {
	for i := range d {
		d[i].Tick()
	}
}

func AllDiscsAlign(d []Disc) bool {
	for i := range d {
		if (d[i].currPos+d[i].id)%d[i].ttlPos != 0 {
			return false
		}
	}
	return true
}

type Disc struct {
	id       int
	ttlPos   int
	currPos  int
	startPos int
	numTicks int
	bufTicks int
}

func CreateDisc(id, ttl, curr int) *Disc {
	d := new(Disc)
	d.id = id
	d.ttlPos = ttl
	d.currPos = curr
	d.startPos = curr
	return d
}

func (d *Disc) Tick() {
	d.currPos = (d.currPos + 1) % d.ttlPos
	d.numTicks++
}

func stdinToStringSlice() []string {
	var input []string
	scanner := bufio.NewScanner(os.Stdin)
	for scanner.Scan() {
		input = append(input, scanner.Text())
	}
	return input
}

func atoi(i string) int {
	var ret int
	var err error
	if ret, err = strconv.Atoi(i); err != nil {
		log.Fatal("Invalid Atoi")
	}
	return ret
}

func ClearScreen() {
	fmt.Print("\033[H\033[2J")
}
