package main

import (
	"AOC2021/src/helper"
	"fmt"
	"os"
	"strconv"
	"strings"
)

type foldingInfo struct {
	alignment string
	length    int
}

func main() {
	args := os.Args[1:]
	input, err := helper.GetInput(args[0])
	if err != nil {
		fmt.Println(err)
	}
	var points [][2]int
	var folds []foldingInfo
	for _, row := range input {
		if helper.ContainsCharacter(row, ",") {
			splitRow, _ := helper.MapToNumber(strings.Split(row, ","))
			xValue := splitRow[0]
			yValue := splitRow[1]
			points = append(points, [2]int{xValue, yValue})
		}
		if helper.ContainsCharacter(row, "=") {
			splitRow := strings.Split(row[10:], "=")
			aligment := splitRow[0][1:]
			length, _ := strconv.Atoi(splitRow[1])
			folds = append(folds, foldingInfo{aligment, length})
		}
	}
	part1(points, folds)
	part2(points, folds)
}

func part1(points [][2]int, folds []foldingInfo) {
	step1 := foldPaper(points, folds[0])
	set := make(map[[2]int]struct{})
	for _, point := range step1 {
		set[point] = struct{}{}
	}
	fmt.Println(len(set))
}
func part2(points [][2]int, folds []foldingInfo) {
	for _, fold := range folds {
		points = foldPaper(points, fold)
	}
	printPaper(points)
}

func foldPaper(points [][2]int, fold foldingInfo) [][2]int{
	var newPaper [][2]int
	for _, point := range points {
		newPaper = append(newPaper, foldPoint(point, fold))
	}
	return newPaper
}

func foldPoint(inputPoint [2]int, fold foldingInfo) [2]int {
	direction := 1
	if fold.alignment == "x" {
		direction = 0
	}

	if inputPoint[direction] > fold.length {
		inputPoint[direction] = fold.length - (inputPoint[direction] - fold.length)
	}
	return inputPoint
}

func printPaper(points [][2]int) {
	maxX := 0
	maxY := 0
	for _, point := range points {
		if point[0] > maxX {
			maxX = point[0]
		}
		if point[1] > maxY {
			maxY = point[1]
		}
	}
	paper := make([][]rune, maxY+1)
	for i := 0; i <= maxY; i++ {
		for j := 0; j <= maxX; j++ {
			paper[i] = append(paper[i], ' ')
		}
	}
	for _, point := range points {
		paper[point[1]][point[0]] = '#'
	}
	for _, row := range paper {
		fmt.Println(string(row))
	}
}
