package main

import (
	"fmt"
	"strings"

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

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

func part1(inp []string) {
	c := NewCPU()
	c.LoadProgram(inp)
	c.DoPart = 1
	fmt.Println(c.Run())
}

func part2(inp []string) {
	c := NewCPU()
	c.LoadProgram(inp)
	c.DoPart = 2
	c.Run()
	fmt.Println()
}

type CPU struct {
	cycle int
	X     int

	prog    []string
	working string

	DoPart int
}

func NewCPU() *CPU {
	return &CPU{cycle: 1, X: 1}
}

func (c *CPU) Signal() int { return c.cycle * c.X }
func (c *CPU) LoadProgram(inp []string) {
	c.prog = make([]string, len(inp))
	copy(c.prog, inp)
}
func (c *CPU) Run() int {
	var result int
	var pos int
	for i := 0; i < len(c.prog); {
		if c.DoPart == 2 {
			if pos == 0 {
				fmt.Println()
			}
			if c.X >= pos-1 && c.X <= pos+1 {
				fmt.Print("#")
			} else {
				fmt.Print(".")
			}
			pos++
			if pos == 40 {
				pos = 0
			}
		}
		c.cycle++
		if len(c.working) > 0 {
			c.doWork()
		} else {
			switch c.prog[i] {
			case "noop":
				c.working = ""
			default:
				c.working = c.prog[i]
			}
			i++
		}
		if c.DoPart == 1 {
			if c.cycle == 20 || c.cycle == 60 || c.cycle == 100 || c.cycle == 140 || c.cycle == 180 || c.cycle == 220 {
				result = c.Signal() + result
			}
		}
	}
	return result
}

func (c *CPU) doWork() {
	pts := strings.Fields(c.working)
	switch pts[0] {
	case "addx":
		val := h.Atoi(pts[1])
		c.X += val
	}
	c.working = ""
}