package main

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

type coord struct {
	row, col int
}

type fold struct {
	direction byte
	value     int
}

type manual struct {
	paper map[coord]bool
	folds []fold
}

func main() {
	if err := myMain(); err != nil {
		log.Println(err)
	}
}

func myMain() error {
	m, err := parseInput("input.txt")
	if err != nil {
		return err
	}

	log.Println(len(solveFirst(m).paper))

	log.Println(solveSecond(m))

	return nil
}

func solveSecond(m manual) manual {
	for _, f := range m.folds {
		m.doFold(f)
	}
	return m
}

func solveFirst(m manual) manual {
	m.doFold(m.folds[0])
	return m
}

func (m manual) doFold(f fold) {
	switch f.direction {
	case 'y':
		for item := range m.paper {
			if item.row > f.value {
				delete(m.paper, item)
				m.paper[coord{f.value - (item.row - f.value), item.col}] = true
			}
		}
	case 'x':
		for item := range m.paper {
			if item.col > f.value {
				delete(m.paper, item)
				m.paper[coord{item.row, f.value - (item.col - f.value)}] = true
			}
		}
	default:
		panic("no way")
	}
}

func (m manual) String() string {
	rows, cols := 0, 0
	for item := range m.paper {
		if item.col > cols {
			cols = item.col
		}
		if item.row > rows {
			rows = item.row
		}
	}
	// log.Println(cols, rows) // x, y
	ret := strings.Builder{}
	ret.WriteByte('\n')
	for y := 0; y <= rows; y++ {
		for x := 0; x <= cols; x++ {
			if m.paper[coord{y, x}] {
				ret.WriteByte('#')
			} else {
				ret.WriteByte('.')
			}
		}
		ret.WriteByte('\n')
	}
	return ret.String()
}

func parseInput(fileName string) (manual, error) {
	var ret = manual{}
	ret.paper = map[coord]bool{}
	fd, err := os.Open(fileName)
	if err != nil {
		return ret, err
	}
	defer fd.Close()

	buf := bufio.NewScanner(fd)
	for buf.Scan() {
		if buf.Text() == "" {
			continue
		}
		tmp := strings.Split(buf.Text(), ",")
		if len(tmp) == 2 {
			crd := coord{}

			crd.col, err = strconv.Atoi(tmp[0])
			if err != nil {
				return ret, err
			}
			crd.row, err = strconv.Atoi(tmp[1])
			if err != nil {
				return ret, err
			}

			ret.paper[crd] = true
		} else { // parsing folds
			fld := fold{}
			tmp := strings.TrimPrefix(buf.Text(), "fold along ")

			fld.direction = tmp[0]
			fld.value, err = strconv.Atoi(tmp[2:])
			if err != nil {
				return ret, err
			}

			ret.folds = append(ret.folds, fld)
		}
	}

	return ret, nil
}