package day10

import (
	"fmt"
)

type Point struct {
	X, Y   int
	Xv, Yv int
}

func (p *Point) Move() {
	p.X += p.Xv
	p.Y += p.Yv
}

func (p *Point) Reverse() {
	p.X -= p.Xv
	p.Y -= p.Yv
}

func CalculateRange(points []*Point) int {
	xMin, xMax, yMin, yMax := findBounds(points)
	return xMax - xMin + yMax - yMin
}

func DrawPoints(points []*Point) {
	pointArr := makeBuffer(points)

	// print the buffer
	for y := 0; y < len(pointArr[0]); y++ {
		for x := 0; x < len(pointArr); x++ {
			if pointArr[x][y] != 0 {
				fmt.Printf("%c", pointArr[x][y])
			} else {
				fmt.Printf(".")
			}
		}
		fmt.Println()
	}
}

// findBounds returns xMin, xMax, yMin, and yMax from the provided points.
func findBounds(points []*Point) (int, int, int, int) {
	// find min and max values
	xMin := points[0].X
	xMax := points[0].X
	yMin := points[0].Y
	yMax := points[0].Y

	for _, point := range points {
		if point.X < xMin {
			xMin = point.X
		}
		if point.X > xMax {
			xMax = point.X
		}
		if point.Y < yMin {
			yMin = point.Y
		}
		if point.Y > yMax {
			yMax = point.Y
		}
	}

	return xMin, xMax, yMin, yMax
}

func makeBuffer(points []*Point) [][]byte {
	xMin, xMax, yMin, yMax := findBounds(points)

	// get the total magnitude; we'll do adjustments later
	xRange := xMax - xMin
	yRange := yMax - yMin

	// construct the buffer
	pointArr := make([][]byte, xRange+1)
	for i := 0; i < len(pointArr); i++ {
		pointArr[i] = make([]byte, yRange+1)
	}

	// put the points into the buffer
	for _, p := range points {
		// the x and y values are adjusted by the mins
		x := p.X - xMin
		y := p.Y - yMin

		pointArr[x][y] = '#'
	}

	return pointArr
}