package main

import (
	"fmt"
	"time"

	//	"math/rand"
	"os"
	//	"strings"
	//	"time"
	"adventofcode2024/day01"
	"adventofcode2024/day02"
	"adventofcode2024/day03"
	"adventofcode2024/day04"
	"adventofcode2024/day06"
	"adventofcode2024/day07"
	"adventofcode2024/day08"
	"adventofcode2024/day09"
	"adventofcode2024/day10"
	"adventofcode2024/day11"
	"adventofcode2024/day12"
	"adventofcode2024/day13"
	"adventofcode2024/day14"
	"adventofcode2024/day15"
	"adventofcode2024/day16"
	"adventofcode2024/day17"
	"adventofcode2024/day18"
	"adventofcode2024/day19"
	"adventofcode2024/utils"
)

// Usage: go run main.go <NN>
// assumes input is in day<NN>/input.txt
func main() {
	d := day()
	fmt.Printf("Running day %02d\n", d)
	start := time.Now()
	switch d {
	case 1:
		fmt.Printf("part 1: %d\n", day01.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day01.Part2(utils.Readfile(d)))
	case 2:
		fmt.Printf("part 1: %d\n", day02.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day02.Part2(utils.Readfile(d)))
	case 3:
		fmt.Printf("part 1: %d\n", day03.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day03.Part2(utils.Readfile(d)))
	case 4:
		fmt.Printf("part 1: %d\n", day04.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day04.Part2(utils.Readfile(d)))
	case 6:
		fmt.Printf("part 1: %d\n", day06.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day06.Part2(utils.Readfile(d)))
	case 7:
		fmt.Printf("part 1: %d\n", day07.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day07.Part2(utils.Readfile(d)))
	case 8:
		fmt.Printf("part 1: %d\n", day08.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day08.Part2(utils.Readfile(d)))
	case 9:
		fmt.Printf("part 1: %d\n", day09.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day09.Part2(utils.Readfile(d)))
	case 10:
		fmt.Printf("part 1: %d\n", day10.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day10.Part2(utils.Readfile(d)))
	case 11:
		fmt.Printf("part 1: %d\n", day11.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day11.Part2(utils.Readfile(d)))
	case 12:
		fmt.Printf("part 1: %d\n", day12.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day12.Part2(utils.Readfile(d)))
	case 13:
		fmt.Printf("part 1: %d\n", day13.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day13.Part2(utils.Readfile(d)))
	case 14:
		fmt.Printf("part 1: %d\n", day14.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day14.Part2(utils.Readfile(d)))
	case 15:
		fmt.Printf("part 1: %d\n", day15.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day15.Part2(utils.Readfile(d)))
	case 16:
		fmt.Printf("part 1: %d\n", day16.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day16.Part2(utils.Readfile(d)))
	case 17:
		fmt.Printf("part 1: %s\n", day17.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day17.Part2(utils.Readfile(d)))
	case 18:
		fmt.Printf("part 1: %d\n", day18.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day18.Part2(utils.Readfile(d)))
	case 19:
		fmt.Printf("part 1: %d\n", day19.Part1(utils.Readfile(d)))
		fmt.Printf("part 2: %d\n", day19.Part2(utils.Readfile(d)))
	default:
		panic(fmt.Errorf("no such day: %d", d))
	}
	elapsed := time.Since(start)
	fmt.Printf("Execution time: %s\n", elapsed)
}

// Reads day from os.Args.
func day() int {
	latest := 19
	if len(os.Args) == 1 {
		return latest
	}

	if os.Args[1] == "next" {
		genNext(latest + 1)
		os.Exit(0)
	}
	day := utils.MustAtoi(os.Args[1])
	return day
}

func genNext(n int) {
	os.Mkdir(fmt.Sprintf("day%02d", n), 0755)
	f, err := os.Create(fmt.Sprintf("day%02d/day%02d.go", n, n))
	utils.PanicOnErr(err)
	defer f.Close()
	f.WriteString(fmt.Sprintf(`package day%02d

func Part1(input string) int {
	return 0
}

func Part2(input string) int {
	return 0
}
`, n))
	fmt.Printf("wrote day%02d/day%02d.go\n", n, n)

	f, err = os.Create(fmt.Sprintf("day%02d/day%02d_test.go", n, n))
	utils.PanicOnErr(err)
	defer f.Close()
	f.WriteString(fmt.Sprintf(`package day%02d

import (
	"testing"

	"github.com/stretchr/testify/require"
)

func TestPart1(t *testing.T) {
	r := Part1("")
	require.Equal(t, 0, r)
}

func TestPart2(t *testing.T) {
	r := Part2("")
	require.Equal(t, 0, r)
}
`, n))
	fmt.Printf("wrote day%02d/day%02d_test.go\n", n, n)
	utils.GenInputFile(n)

}
