# Screens have to clear the screen themselves.

import ugfx, time, appglue, random, uos

language = None
languages = ["English", "German", "Dutch"]

instructions = [
	[
		"You will be playing a simple game of memory. You can navigate through the field with the directional buttons. (Press RIGHT now to continue)",
		"By pressing A, you can turn the selected card. After turning one card, select another card. If they match, they will be removed. The goal is to eliminate all cards.",
		"I hope you will enjoy this little game!"
	],
	[
		"Dies ist ein einfaches Memory. Du kannst mit den Pfeiltasten durch das Spiel navigieren. (Weiter mit RECHTS)",
		"Druecke A, um die ausgewaehlte Karte aufzudecken. Nachdem du die Karte aufgedeckt hast, waehle eine weitere Karte aus. Ziel ist es alle Paare zu finden.",
		"Viel Spass!"
	],
	[
		"U gaat het spel memory spelen. U kunt door het veld heen navigeren met de pijltjestoetsen. (Druk nu op RECHTS)",
		"Door op A te drukken, kunt u de geselecteerde kaart omdraaien. Vervolgens kiest u een andere kaart en draait deze om. Zijn ze gelijk, worden ze verwijderd.",
		"Het doel is dus om alle kaarten te elimineren. Ik hoop dat u het leuk gaat vinden!"
	]
]
instructionsPage = None

font = "Roboto_Regular12"

msg_you_have_selected = [
	"You have selected English!",
	"Sie haben Deutsch gewahlt!",
	"U heeft Nederlands gekozen!"
]

msg_press_a_to_start = [
	"Press A to start",
	"Drucke A um zu starten",
	"Druk A om te starten"
]

msg_score = [
	"{0} points!",
	"{0} Punkte!",
	"{0} punten!"
]

msg_control_buttons_hint = [
	"You can exit the game by pressing SELECT, and you can go back to the menu by pressing START.",
	"Druecke SELECT um das Spiel zu beenden, START um zum Menu zurueckzukehren.",
	"U kunt het spel afsluiten door op SELECT te drukken, en terug naar het menu gaan met START."
]

cards = None
cardRowSelected = None
cardColSelected = None
flippedCards = None
solvedCards = None
flips = None

def __exit_app(pressed):
	if pressed:
		appglue.home()

def __reinit_app(pressed):
	if pressed:
		init_app()

def reset_input():
	ugfx.input_init()
	ugfx.input_attach(ugfx.BTN_SELECT, __exit_app)
	ugfx.input_attach(ugfx.BTN_START, __reinit_app)

def clear_screen():
	clear_screen_wo_flush()
	ugfx.flush()

def clear_screen_wo_flush():
	ugfx.clear(ugfx.BLACK)
	ugfx.flush()
	ugfx.clear(ugfx.WHITE)

def screen_language_selection():
	reset_input()
	clear_screen_wo_flush()

	ugfx.input_attach(ugfx.JOY_LEFT, lambda pressed: language_selected_handler(0) if pressed else None)
	ugfx.input_attach(ugfx.JOY_UP, lambda pressed: language_selected_handler(1) if pressed else None)
	ugfx.input_attach(ugfx.JOY_RIGHT, lambda pressed: language_selected_handler(2) if pressed else None)

	# Height of lines: 12l + 6(l-1)
	ugfx.string_box(0, 0, 296, 32, "Press LEFT for " + languages[0] + ", press UP for " + languages[1] + ", press RIGHT for " + languages[2] + ".", font, ugfx.BLACK, ugfx.justifyCenter)
	ugfx.string_box(0, 96, 296, 32, msg_control_buttons_hint[0], font, ugfx.BLACK, ugfx.justifyCenter)
	ugfx.flush()

def language_selected_handler(x):
	global language

	reset_input()
	
	language = x

	ugfx.fill_rounded_box(0, 0, 296, 32, 0, ugfx.BLACK)
	ugfx.fill_rounded_box(0, 96, 296, 32, 0, ugfx.BLACK)
	ugfx.string_box(0, 58, 296, 12, msg_you_have_selected[language], font, ugfx.BLACK, ugfx.justifyCenter)
	ugfx.flush()
	time.sleep_ms(1000)
	screen_instructions()

def screen_instructions():
	reset_input()
	# This method does not use display directly, so not clearing screen here

	instructions_page_changed_handler(0)

	ugfx.input_attach(ugfx.JOY_LEFT, lambda pressed: instructions_page_changed_handler(instructionsPage - 1) if instructionsPage > 0 and pressed else None)
	ugfx.input_attach(ugfx.JOY_RIGHT, lambda pressed: instructions_page_changed_handler(instructionsPage + 1) if instructionsPage < len(instructions[language]) - 1 and pressed else None)
	ugfx.input_attach(ugfx.BTN_A, lambda pressed: instructions_page_start_handler() if pressed else None)

def instructions_page_changed_handler(page):
	global instructionsPage

	instructionsPage = page

	clear_screen_wo_flush()

	ugfx.string_box(0, 38, 296, 52, instructions[language][instructionsPage], font, ugfx.BLACK, ugfx.justifyCenter)

	for x in range(0, len(instructions[language])):
		if x == instructionsPage:
			ugfx.fill_rounded_box(133 + 10 * x, 112, 10, 10, 0, ugfx.BLACK)
		else:
			ugfx.fill_rounded_box(133 + 10 * x + 3, 112 + 3, 4, 4, 0, ugfx.BLACK)

	ugfx.string_box(0, 111, 133, 12, "RainbowTragedy", font, ugfx.BLACK, ugfx.justifyCenter)

	ugfx.string_box(163, 111, 133, 12, msg_press_a_to_start[language], font, ugfx.BLACK, ugfx.justifyCenter)

	ugfx.flush()

def instructions_page_start_handler():
	reset_input()

	screen_game()

def screen_game():
	global cards, cardRowSelected, cardColSelected, flips, flippedCards, solvedCards

	reset_input()
	# This method does not use display directly, so not clearing screen here

	# Initialize flipped and solved cards
	flippedCards = []
	solvedCards = []

	# Select first card
	cardRowSelected = 0
	cardColSelected = 0

	# Initialize flip counter
	flips = 0

	# Create cards
	cards = []

	possible_chars = list(range(65, 91))

	for i in range(8 * 3 / 2):
		char = chr(possible_chars.pop(random.randint(0, len(possible_chars) - 1)))
		cards.append(char)
		cards.append(char)

	_shuffle_array(cards)

	clear_screen()
	game_draw()

	ugfx.input_attach(ugfx.JOY_LEFT, game_move_left_handler)
	ugfx.input_attach(ugfx.JOY_RIGHT, game_move_right_handler)
	ugfx.input_attach(ugfx.JOY_UP, game_move_up_handler)
	ugfx.input_attach(ugfx.JOY_DOWN, game_move_down_handler)
	ugfx.input_attach(ugfx.BTN_A, game_card_selected_handler)

def game_draw():
	global cards

	ugfx.clear(ugfx.WHITE)

	# There will be 8x3 boxes of size 37x42 and some padding
	for i in range(len(cards)):
		coordinates = (i % 8, int(i / 8))
		col = coordinates[0]
		row = coordinates[1]

		if coordinates in flippedCards:
			ugfx.string_box(col * 37, 1 + row * 42, 37, 42, cards[col + row * 8], font, ugfx.BLACK, ugfx.justifyCenter)
		else:
			ugfx.fill_rounded_box(col * 37 + 3, 1 + row * 42 + 3, 37 - 6, 42 - 6, 0, ugfx.BLACK)

		if coordinates in solvedCards:
			ugfx.string_box(col * 37, 1 + row * 42, 37, 42, cards[col + row * 8], font, ugfx.WHITE, ugfx.justifyCenter)

		if col == cardColSelected and row == cardRowSelected:
			ugfx.rounded_box(col * 37, 1 + row * 42, 37, 42, 3, ugfx.BLACK)

	ugfx.flush()

def game_clear_cards(card1, card2):
	ugfx.fill_rounded_box(card1[0] * 37 + 3, 1 + card1[1] * 42 + 3, 37 - 6, 42 - 6, 0, ugfx.BLACK)
	ugfx.fill_rounded_box(card2[0] * 37 + 3, 1 + card2[1] * 42 + 3, 37 - 6, 42 - 6, 0, ugfx.BLACK)
	ugfx.flush()
	ugfx.fill_rounded_box(card1[0] * 37 + 3, 1 + card1[1] * 42 + 3, 37 - 6, 42 - 6, 0, ugfx.WHITE)
	ugfx.fill_rounded_box(card2[0] * 37 + 3, 1 + card2[1] * 42 + 3, 37 - 6, 42 - 6, 0, ugfx.WHITE)
	ugfx.flush()
	ugfx.fill_rounded_box(card1[0] * 37 + 3, 1 + card1[1] * 42 + 3, 37 - 6, 42 - 6, 0, ugfx.BLACK)
	ugfx.fill_rounded_box(card2[0] * 37 + 3, 1 + card2[1] * 42 + 3, 37 - 6, 42 - 6, 0, ugfx.BLACK)
	ugfx.flush()
	ugfx.fill_rounded_box(card1[0] * 37 + 3, 1 + card1[1] * 42 + 3, 37 - 6, 42 - 6, 0, ugfx.WHITE)
	ugfx.fill_rounded_box(card2[0] * 37 + 3, 1 + card2[1] * 42 + 3, 37 - 6, 42 - 6, 0, ugfx.WHITE)
	ugfx.flush()

def game_move_up_handler(pressed):
	global cardRowSelected

	if pressed and cardRowSelected > 0:
		cardRowSelected -= 1
		game_draw()

def game_move_down_handler(pressed):
	global cardRowSelected
	
	if pressed and cardRowSelected < 2:
		cardRowSelected += 1
		game_draw()

def game_move_left_handler(pressed):
	global cardColSelected
	
	if pressed and cardColSelected > 0:
		cardColSelected -= 1
		game_draw()

def game_move_right_handler(pressed):
	global cardColSelected
	
	if pressed and cardColSelected < 7:
		cardColSelected += 1
		game_draw()

def game_card_selected_handler(pressed):
	global flippedCards, flips

	coordinates = (cardColSelected, cardRowSelected)

	if not pressed or coordinates in flippedCards or coordinates in solvedCards:
		return

	flippedCards.append(coordinates)

	game_draw()

	if len(flippedCards) == 2:
		pos1 = flippedCards[0][0] + flippedCards[0][1] * 8
		pos2 = flippedCards[1][0] + flippedCards[1][1] * 8

		flips += 1

		if cards[pos1] == cards[pos2]:
			solvedCards.append(flippedCards[0])
			solvedCards.append(flippedCards[1])
			flippedCards.clear()
			game_draw()

			if len(solvedCards) == 8 * 3:
				screen_score()
		else:
			time.sleep_ms(1000)
			game_clear_cards(flippedCards[0], flippedCards[1])
			flippedCards.clear()
			game_draw()

def screen_score():
	reset_input()
	clear_screen_wo_flush()

	ugfx.string_box(0, 53, 296, 22, msg_score[language].format(str(100 - flips)), "PermanentMarker22", ugfx.BLACK, ugfx.justifyCenter)
	ugfx.string_box(0, 96, 296, 32, msg_control_buttons_hint[language], font, ugfx.BLACK, ugfx.justifyCenter)
	ugfx.flush()

def _shuffle_array(arr):
	y = len(arr) - 1
	while y != -1:
		arr.append(arr.pop(random.randint(0, y)))
		y -= 1

def init_app():
	random.seed(int.from_bytes(uos.urandom(4), 'big'))
	clear_screen()
	ugfx.init()
	screen_language_selection()

init_app()