package day04

import (
	"math"
	"regexp"
	"strings"

	"fmt"

	"adventofcode2023/utils"

	mapset "github.com/deckarep/golang-set/v2"
)

type Game struct {
	ID      int
	matches int
	count  int
	winners mapset.Set[int]
	cards mapset.Set[int]
}

func Part1(input string) int {
	games, err := parseGames(input)
	if err != nil {
		fmt.Println("Error:", err)
		return -1
	}

	points := 0.0
	for _, game := range games {
		matches := len(game.cards.Intersect(game.winners).ToSlice())
		if matches > 0 {
			points += math.Pow(2, float64(matches - 1))
		}
	}
	return int(points)
}

func Part2(input string) int {
	games, err := parseGames(input)
	if err != nil {
		fmt.Println("Error:", err)
		return -1
	}

	for i, game := range games {
		matches := game.cards.Intersect(game.winners).ToSlice()
		games[i].matches = len(matches)
		games[i].count = 1
	}

	for i:=0;i<len(games);i++{
		for j:=0;j<games[i].count;j++ {
			for k:=1;k<=games[i].matches;k++ {
				games[i+k].count++
			}
		}
	}
	
	cards := 0
	for i:=0;i<len(games);i++{
		cards += games[i].count
	}
	return cards
}

func parseGames(input string) ([]Game, error) {
	
	var game Game
	var games []Game

	lines := strings.Split(input, "\n")
	for _, line := range lines {
		reID := regexp.MustCompile(`Card\s*(\d+):(.*) \| (.*)`)
		match := reID.FindStringSubmatch(line)
		if len(match) != 4 {
			return games, fmt.Errorf("unable to extract game")
		}

		game.ID = utils.MustAtoi(match[1])
		game.winners = getNumbers(match[2])
		game.cards = getNumbers(match[3])

		games = append(games, game)
	}
	return games, nil
}

func getNumbers(input string) mapset.Set[int] {
	tokens := strings.Fields(input)
	var numbers []int
	for _, token := range tokens {
		num := utils.MustAtoi(token)
		numbers = append(numbers, num)
	}
	return mapset.NewSet[int](numbers...)
}