test_that("no regressions in `game_systems()`", {
	expect_error(game_systems("boobear"), "Don't have a customized configuration for font")
})


test_that("removed `style` argument errors", {
	expect_snapshot(error = TRUE, game_systems(style = "dejavu3d"))
})

test_that("no regressions in `game_systems()` figures", {
	skip_on_ci()
	skip_if_not_installed("vdiffr")
	library("vdiffr")
	# d6 dice
	envir <- game_systems()
	suppressMessages(
		{
			expect_doppelganger("dice-d6", function() {
				grid.piece(
					"die_face",
					x = 1:6,
					y = 1,
					default.units = "in",
					rank = 1:6,
					suit = 1:6,
					op_scale = 0.5,
					cfg = envir$dice
				)
				grid.piece(
					"die_face",
					x = 1:6,
					y = 2,
					default.units = "in",
					rank = 1:6,
					suit = 1:6,
					op_scale = 0.5,
					cfg = envir$dice_numeral
				)
				grid.piece(
					"die_face",
					x = 1:6,
					y = 3,
					default.units = "in",
					rank = 1:6,
					suit = 1:6,
					op_scale = 0.5,
					cfg = envir$dice_fudge
				)
			})
		},
		classes = "piecepackr_affine_transformation"
	)

	# dominoes
	skip_if_not_installed("systemfonts") # prevent buggy cairo interaction with "dejavu" style
	envir <- game_systems("dejavu")
	expect_doppelganger("dominoes", function() {
		grid.piece(
			"tile_face",
			x = rep(6:1, 3),
			y = rep(2 * 3:1, each = 6),
			suit = 1:18,
			rank = 1:18 + 1,
			cfg = paste0(
				"dominoes_",
				rep(rev(c("black", "red", "green", "blue", "yellow", "white")), 2)
			),
			default.units = "in",
			envir = envir,
			op_scale = 0.5
		)
	})
	expect_error(xya_pips_cards(11), "Don't know pip pattern for 11 pips")
	expect_error(xya_pips_dominoes(19), "Don't know pip pattern for 19 pips")
	for (i in 0:10) {
		expect_equal(nrow(xya_pips_cards(i)), i)
	}

	# checkers
	expect_doppelganger("checkers", function() {
		df2 <- tibble(
			piece_side = "board_face",
			x = c(4, 6),
			y = c(4, 6),
			suit = c(2, 4),
			rank = c(4, 2),
			cfg = "checkers2"
		)
		df1f <- tibble(
			piece_side = "board_face",
			x = c(1, 2),
			y = c(1, 6),
			suit = c(1, 5),
			rank = c(2, 4),
			cfg = "checkers1"
		)
		df1b <- tibble(
			piece_side = "board_back",
			x = 5,
			y = 1,
			suit = 1,
			rank = 2,
			cfg = "checkers1"
		)
		df_bit1 <- tibble(
			piece_side = "bit_back",
			x = rep_len(1, 6L),
			y = rep_len(1, 6L),
			suit = 1:6,
			rank = 1:6,
			cfg = "checkers1"
		)
		df_bit2 <- tibble(
			piece_side = "bit_face",
			x = 2:7,
			y = 2:7,
			suit = 6:1,
			rank = 1:6,
			cfg = "checkers1"
		)
		df_bit3 <- tibble(
			piece_side = "bit_back",
			x = 5,
			y = 7,
			suit = 4L,
			rank = 4L,
			cfg = "checkers2"
		)
		df <- rbind(df2, df1f, df1b, df_bit3, df_bit2, df_bit1)
		df_bit4 <- tibble(
			piece_side = "bit_face",
			x = 7,
			y = 5,
			suit = 2L,
			rank = 4L,
			cfg = "checkers2"
		)
		df <- rbind(df2, df1f, df1b, df_bit4, df_bit3, df_bit2, df_bit1)
		pmap_piece(df, default.units = "in", envir = envir, op_scale = 0.5, trans = op_transform)
	})

	# chess
	# df <- tibble(piece_side = "bit_face", x = rep(1:6, 6L), y = rep(6:1, each=6L),
	#              rank = x, suit = y, cfg = "chess1")
	# pmap_piece(df, default.units="in", envir=envir, op_scale=0.5, trans=op_transform)
	# df <- tibble(piece_side = "bit_face", x = rep(seq.int(1, by=2, length.out=6L), 6L), y = rep(6:1, each=6L),
	#              rank = x, suit = y, cfg = "chess2")
	# pmap_piece(df, default.units="in", envir=envir, op_scale=0.5, trans=op_transform)

	# joystick pawns
	cfg <- game_systems(pawn = "joystick")$piecepack
	df <- tibble(piece_side = "pawn_top", x = 1:4, y = 1:4, suit = 1:4)
	expect_doppelganger("joystick", function() {
		pmap_piece(df, default.units = "in", cfg = cfg)
	})
	expect_doppelganger("joystick-op", function() {
		pmap_piece(df, default.units = "in", cfg = cfg, op_scale = 0.5)
	})

	# go
	expect_doppelganger("go", function() {
		dfb <- tibble(piece_side = "board_face", x = 10, y = 10, suit = 2)
		dfB <- tibble(
			piece_side = "bit_face",
			x = c(2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 6, 7, 7, 8),
			y = c(11, 13, 14, 12, 15, 13, 16, 12, 16, 12, 13, 16, 15, 17, 16),
			suit = 4
		)
		dfR <- tibble(
			piece_side = "bit_face",
			x = c(3, 3, 4, 5, 6, 7, 8, 8, 9),
			y = c(2:3, 4, 3, 4, 4, 2:3, 2),
			suit = 1
		)
		dfY <- tibble(
			piece_side = "bit_face",
			x = 20 - c(3, 4, 5, 5, 7, 8, 9, 9, 9),
			y = 20 - c(3, 2, 2:3, 2, 5, 2:4),
			suit = 5
		)
		dfG <- tibble(
			piece_side = "bit_face",
			x = 20 - c(3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 6, 6),
			y = c(4, 5, 7, 12, 13, 6, 7, 10, 11, 7, 9, 10, 8, 9),
			suit = 3
		)
		dfK <- tibble(
			piece_side = "bit_face",
			x = c(
				rep(2, 5),
				rep(3, 5),
				rep(4, 4),
				rep(5, 5),
				rep(6, 2),
				rep(7, 4),
				rep(8, 7),
				rep(9, 5),
				rep(10, 5),
				rep(11, 4),
				rep(12, 5),
				rep(13, 6),
				rep(14, 2),
				rep(15, 6),
				rep(16, 6),
				rep(17, 2)
			),
			y = c(
				2:3,
				8:9,
				12,
				4:5,
				10,
				13:14,
				5,
				10,
				14:15,
				6,
				8,
				10:11,
				14,
				5,
				11,
				5,
				7,
				12,
				14,
				4,
				7,
				9,
				11:13,
				15,
				3:4,
				11,
				14,
				16,
				8:9,
				14:16,
				3,
				6,
				8,
				15,
				9:11,
				16,
				18,
				6,
				8:9,
				11:12,
				16,
				6:7,
				5:6,
				8,
				11:12,
				16,
				3,
				5,
				12,
				14,
				16:17,
				3,
				16
			),
			suit = 2
		)
		dfW <- tibble(
			piece_side = "bit_face",
			x = c(
				3:5,
				rep(6, 3),
				rep(7, 3),
				rep(8, 2),
				rep(9, 5),
				rep(10, 3),
				rep(11, 4),
				rep(12, 4),
				rep(13, 2),
				14
			),
			y = c(
				9,
				9,
				9,
				7:8,
				10,
				8,
				10:11,
				8,
				10,
				8:10,
				12:13,
				10:11,
				13,
				9,
				11,
				13:14,
				7:8,
				12:13,
				7,
				10,
				11
			),
			suit = 6
		)
		df <- rbind(dfb, dfB, dfR, dfY, dfG, dfK, dfW)

		cfg <- game_systems("sans")$go
		pmap_piece(
			df,
			grid.piece,
			cfg = cfg,
			trans = op_transform,
			default.units = "in",
			op_scale = 0.5
		)
	})

	# playing cards
	cfg <- game_systems("sans", border = FALSE)$playing_cards_colored
	expect_doppelganger("ten-of-clubs", function() {
		grid.piece("card_face", suit = 3, rank = 10, cfg = cfg, default.units = "npc")
	})
	expect_doppelganger("king-of-stars", function() {
		suppressMessages(
			{
				grid.piece("card_face", suit = 5, rank = 13, cfg = cfg, default.units = "npc")
			},
			classes = "piecepackr_fill_stroke"
		)
	})
	expect_doppelganger("red-joker", function() {
		grid.piece("card_face", suit = 1, rank = 14, cfg = cfg, default.units = "npc")
	})
	cfg <- game_systems("sans", border = FALSE)$playing_cards_tarot
	expect_doppelganger("black-joker-no-star", function() {
		grid.piece("card_face", suit = 3, rank = 15, cfg = cfg, default.units = "npc")
	})
	expect_doppelganger("knight-of-diamonds", function() {
		grid.piece("card_face", suit = 4, rank = 12, cfg = cfg, default.units = "npc")
	})

	# morris
	cfg <- envir$morris
	expect_doppelganger("two-morris", function() {
		grid.piece("board_face", x = 4, y = 4, suit = 3, rank = 2, cfg = cfg, default.units = "in")
		grid.piece("bit_back", x = 0:5, y = 0:5, suit = 1:6, cfg = cfg, default.units = "in")
	})
	expect_doppelganger("three-morris", function() {
		grid.piece("board_face", x = 4, y = 4, suit = 3, rank = 3, cfg = cfg, default.units = "in")
		grid.piece("bit_back", x = 0:5, y = 0:5, suit = 1:6, cfg = cfg, default.units = "in")
	})
	expect_doppelganger("six-morris", function() {
		grid.piece("board_face", x = 4, y = 4, suit = 3, rank = 6, cfg = cfg, default.units = "in")
		grid.piece("bit_back", x = 0:5, y = 0:5, suit = 1:6, cfg = cfg, default.units = "in")
	})
	expect_doppelganger("seven-morris", function() {
		grid.piece("board_face", x = 4, y = 4, suit = 3, rank = 7, cfg = cfg, default.units = "in")
		grid.piece("bit_back", x = 0:5, y = 0:5, suit = 1:6, cfg = cfg, default.units = "in")
	})
	expect_doppelganger("nine-morris", function() {
		grid.piece("board_face", x = 4, y = 4, suit = 3, rank = 9, cfg = cfg, default.units = "in")
		grid.piece("bit_back", x = 0:5, y = 0:5, suit = 1:6, cfg = cfg, default.units = "in")
	})
	expect_doppelganger("twelve-morris", function() {
		grid.piece("board_face", x = 4, y = 4, suit = 3, rank = 12, cfg = cfg, default.units = "in")
		grid.piece("bit_back", x = 0:5, y = 0:5, suit = 1:6, cfg = cfg, default.units = "in")
	})

	# alquerque
	cfg <- envir$alquerque
	expect_doppelganger("alquerque", function() {
		grid.piece("board_face", x = 3, y = 3, suit = 3, cfg = cfg, default.units = "in")
		grid.piece("bit_back", x = 1:5, y = 1:5, suit = 1:5, cfg = cfg, default.units = "in")
	})

	# reversi
	expect_doppelganger("reversi", function() {
		envir <- game_systems()
		df_board <- tibble(
			piece_side = "board_face",
			x = 4.5,
			y = 4.5,
			suit = 4,
			rank = 8,
			cfg = "reversi"
		)
		df_bit_face <- tibble(
			piece_side = "bit_face",
			x = 1:6,
			y = 1:6,
			suit = 1:6,
			rank = NA,
			cfg = "reversi"
		)
		df_bit_back <- tibble(
			piece_side = "bit_back",
			x = 1:6 + 1L,
			y = 1:6,
			suit = 1:6,
			rank = NA,
			cfg = "reversi"
		)
		df <- rbind(df_board, df_bit_face, df_bit_back)
		pmap_piece(df, default.units = "in", envir = envir, op_scale = 0.5, trans = op_transform)
	})

	marbles_test <- function(..., round = FALSE, shading = FALSE, f = grid.piece) {
		cur_seed <- .Random.seed
		envir <- game_systems(round = round, shading = shading)
		on.exit(.Random.seed <<- cur_seed, add = TRUE)
		set.seed(42)
		dfb <- data.frame(
			piece_side = "board_face",
			x = 2.5,
			y = 2.5,
			suit = 4L,
			rank = 4L,
			cfg = "marbles"
		)
		dfm <- data.frame(
			piece_side = "bit_back",
			x = c(rep(1:4, 4L), rep(0.5 + rep(1:3, 3L)), rep(2:3, 2L), 2.5),
			y = c(rep(1:4, each = 4L), rep(0.5 + rep(1:3, each = 3L)), rep(2:3, each = 2L), 2.5),
			suit = sample.int(6L, 30L, replace = TRUE),
			rank = 9L,
			cfg = "marbles"
		)
		df <- rbind(dfb, dfm)
		pmap_piece(df, f, envir = envir, ..., default.units = "in")
	}
	# marbles
	expect_doppelganger("marbles", function() {
		marbles_test()
	})
	expect_doppelganger("marbles-op", function() {
		marbles_test(op_scale = 0.5, trans = marbles_transform)
	})

	skip_if_not_installed("svglite", "2.2.2")
	skip_if_not(getRversion() >= "4.2.0")
	write_svg_bleeding_edge <- function(plot, file, title = "") {
		svglite::svglite(file)
		plot()
		invisible(grDevices::dev.off())
	}

	# standard d4 dice
	cfg <- envir$dice_d4
	expect_doppelganger(
		"dice-d4",
		function() {
			grid.piece(
				"die_face",
				x = 1:4,
				y = 1,
				default.units = "in",
				rank = 1:4,
				suit = 1:4,
				op_scale = 0.0,
				cfg = cfg
			)
			grid.piece(
				"die_face",
				x = 1:4,
				y = 2,
				default.units = "in",
				rank = 1:4,
				suit = 1:4,
				op_scale = 0.5,
				cfg = cfg
			)
		},
		writer = write_svg_bleeding_edge
	)

	# standard d8 dice
	cfg <- envir$dice_d8
	expect_doppelganger(
		"dice-d8",
		function() {
			grid.piece(
				"die_face",
				x = 1:8,
				y = 1,
				default.units = "in",
				rank = 1:8,
				suit = c(1:6, 1:2),
				op_scale = 0.0,
				cfg = cfg
			)
			grid.piece(
				"die_face",
				x = 1:8,
				y = 2,
				default.units = "in",
				rank = 1:8,
				suit = c(1:6, 1:2),
				op_scale = 0.5,
				cfg = cfg
			)
		},
		writer = write_svg_bleeding_edge
	)

	# standard d10 dice
	cfg <- envir$dice_d10
	expect_doppelganger(
		"dice-d10",
		function() {
			grid.piece(
				"die_face",
				x = rep(1:5, 2),
				y = rep(1:2, each = 5),
				default.units = "in",
				rank = 1:10,
				suit = rep(1:5, 2),
				op_scale = 0.5,
				cfg = cfg
			)
		},
		writer = write_svg_bleeding_edge
	)

	# percentile d10 dice
	cfg <- envir$dice_d10_percentile
	expect_doppelganger(
		"dice-d10-percentile",
		function() {
			grid.piece(
				"die_face",
				x = rep(1:5, 2),
				y = rep(1:2, each = 5),
				default.units = "in",
				rank = 1:10,
				suit = rep(1:5, 2),
				op_scale = 0.5,
				cfg = cfg
			)
		},
		writer = write_svg_bleeding_edge
	)

	# standard d12 dice
	cfg <- envir$dice_d12
	expect_doppelganger(
		"dice-d12",
		function() {
			grid.piece(
				"die_face",
				x = rep(1:6, 2),
				y = rep(1:2, each = 6),
				default.units = "in",
				rank = 1:12,
				suit = rep(1:6, 2),
				op_scale = 0.5,
				cfg = cfg
			)
		},
		writer = write_svg_bleeding_edge
	)

	# standard d20 dice
	cfg <- envir$dice_d20
	expect_doppelganger(
		"dice-d20",
		function() {
			grid.piece(
				"die_face",
				x = rep(1:5, 4),
				y = rep(1:4, each = 5),
				default.units = "in",
				rank = 1:20,
				suit = rep(1:6, length.out = 20),
				op_scale = 0.5,
				cfg = cfg
			)
		},
		writer = write_svg_bleeding_edge
	)

	# Chinese dominoes
	expect_doppelganger(
		"dominoes-chinese",
		function() {
			df1 <- tibble(
				piece_side = "tile_face",
				suit = c(rep(1, 6L), 2L, rep(2, 4L), rep(3, 3L), 3, rep(4, 3), 5, 5, 6),
				rank = c(1:6, 2L, 3:6, 3:5, 6, 4:6, 5:6, 6),
				cfg = c(rep(
					c("dominoes_chinese", "dominoes_chinese_black", "dominoes_chinese"),
					each = 7L
				)),
				x = rep(1:7, 3L),
				y = c(rep(c(1.5, 4.0, 6.5), each = 7L))
			)
			df2 <- tibble(
				piece_side = "die_face",
				suit = 1,
				rank = 1:6,
				cfg = rep(
					c("dominoes_chinese", "dominoes_chinese_black", "dominoes_chinese"),
					each = 2L
				),
				x = 8.5,
				y = c(1, 2.25, 3.5, 4.75, 6.0, 7.25)
			)
			df <- rbind(df1, df2)
			pmap_piece(
				df,
				envir = game_systems(),
				default.units = "in",
				trans = op_transform,
				op_scale = 0.5
			)
		},
		writer = write_svg_bleeding_edge
	)

	# king of stars (fill + stroke)
	cfg <- game_systems("sans", border = FALSE)$playing_cards_colored
	expect_doppelganger(
		"king-of-stars-fill-stroke",
		function() {
			grid.piece("card_face", suit = 5, rank = 13, cfg = cfg, default.units = "npc")
		},
		writer = write_svg_bleeding_edge
	)

	expect_doppelganger(
		"marbles-shading",
		function() {
			marbles_test(op_scale = 0.5, shading = TRUE, trans = marbles_transform)
		},
		writer = write_svg_bleeding_edge
	)

	# cubes
	expect_doppelganger("cubes", function() {
		grid.piece(
			"bit_face",
			x = rep(6:1, 6),
			y = rep(6:1, each = 6),
			suit = rep(1:6, each = 6),
			rank = rep(6:1, 6),
			default.units = "in",
			op_scale = 0.5,
			cfg = envir$cubes
		)
	})
})
