import display, badge, buttons, time, samd

def set_theme(mytheme):
	global background_color, foreground_color, theme
	theme=mytheme
	if theme=="light":
		background_color=0xFFFFFF
		foreground_color=0
	else:
		background_color=0
		foreground_color=0xFFFFFF

def init_mywindow(mywindowname, mywidth, myheight, pos_x=0, pos_y=0, framed=False):
	try:
		display.windowCreate(mywindowname,mywidth,myheight)
	except ValueError as err:
		if err:
			pass
		else:
			print(err)
	display.drawFill(mywindowname, background_color)
	if framed:
		display.drawRect(mywindowname,0,0,mywidth,myheight,no_fill,foreground_color)
	display.windowMove(mywindowname,pos_x, pos_y)

def play_sound(played_sound):
	sounds = ["treasure found",[4,1,0,1,4,1,4,1,0,1,4,1,4,1,0,1,4,1,4,1,0,1,5,1,6,1,0,1,5,1,6,1,0,1,5,1,6,1,0,1,5,1,6,1,0,1,5,1,4,2],
				"turn left",[1,1,0,1,1,1,0,1,1,1,0,1],
				"turn right",[3,1,0,1,5,1,0,1,4,1,0,1],
				"move ahead",[1,4,0,1,1,4,0,1],
				"fire laser",[3,4,2,3,1,2,0,1],
				"undo",[1,4,0,1],
				"menu",[1,1,0,1]]
	notes=sounds[sounds.index(played_sound)+1]
	i=0
	while i < len(notes)/2:
		fr = notes[i*2]
		t = notes[i*2+1]
		samd.buzzer(fr, t)
		time.sleep(t*0.0625)
		i = i + 1


def display_centered_message(window, pos_x, pos_y, text, color, font):
	mytextwidth=display.getTextWidth(text,font)
	display.drawText(window,pos_x-int(mytextwidth/2),pos_y,text,color,font)

def popup_menu(message, menuitems, popup_window_pos_x, popup_window_pos_y, popup_window_width, popup_window_height, popup_window_border):
	
	def display_popup_menu():
		display.drawRect("popup_menu",1,1,display.width("popup_menu")-2,display.height("popup_menu")-2,fill,background_color)
		display_centered_message("popup_menu",int(display.width("popup_menu")/2),5,message,foreground_color,myfont)
		textwidth=0
		vertical_position=display.height("popup_menu")-(display.getTextHeight(menuitems[0],myfont)+7)#7
		for j in range(len(menuitems)):
			textwidth+=display.getTextWidth(menuitems[j],myfont)
		padding=int((display.width("popup_menu")-textwidth)/(len(menuitems)+1))
		next_text_position=0
		for i in range(len(menuitems)):
			next_text_position+=padding
			if i>0:
				next_text_position+=display.getTextWidth(menuitems[i-1],myfont)
			if i==current_popup_selection:
				display.drawRect("popup_menu",next_text_position-int(padding/2),vertical_position-3,padding+display.getTextWidth(menuitems[i]),8+display.getTextHeight(menuitems[i]),fill,foreground_color)
				display.drawText("popup_menu",next_text_position,vertical_position,menuitems[i],background_color,myfont)
			else:
				display.drawRect("popup_menu",next_text_position-int(padding/2),vertical_position-3,padding+display.getTextWidth(menuitems[i]),8+display.getTextHeight(menuitems[i]),fill,background_color)
				display.drawText("popup_menu",next_text_position,vertical_position,menuitems[i],foreground_color,myfont)
		display.flush()
		
	def popup_menu_action_right(pressed):
		nonlocal current_popup_selection
		if not pressed:
			return
		badge.led(4,1,0,1)
		time.sleep(.1)
		if sound_on: play_sound("menu")
		badge.led(4,0,0,0)
		if current_popup_selection<len(menuitems)-1:
			current_popup_selection+=1
			display_popup_menu()
			
	def popup_menu_action_left(pressed):
		nonlocal current_popup_selection
		if not pressed:
			return
		badge.led(4,1,1,0)
		time.sleep(.1) 
		if sound_on: play_sound("menu")
		badge.led(4,0,0,0)
		if current_popup_selection>0:
			current_popup_selection-=1
			display_popup_menu()

	def popup_menu_action_enter(pressed):
		nonlocal selection_made
		if not pressed:
			return
		badge.led(3,1,0,0)
		time.sleep(.1)
		if sound_on: play_sound("menu")
		badge.led(3,0,0,0)
		selection_made=True

	def detach_popup_menu_actions_from_buttons():
		buttons.detach(buttons.BTN_LEFT)
		buttons.detach(buttons.BTN_RIGHT)
		buttons.detach(buttons.BTN_OK)

	def attach_popup_menu_actions_to_buttons():
		buttons.attach(buttons.BTN_LEFT, popup_menu_action_left)
		buttons.attach(buttons.BTN_RIGHT, popup_menu_action_right)
		buttons.attach(buttons.BTN_OK, popup_menu_action_enter)

	badge.led(6,0,0,0)
	display.windowRemove("popup_menu")
	init_mywindow("popup_menu",popup_window_width,popup_window_height,popup_window_pos_x,popup_window_pos_y,popup_window_border)
	display.windowShow("popup_menu")
	current_popup_selection=0
	display_popup_menu()
	attach_popup_menu_actions_to_buttons()
	selection_made=False
	while not selection_made:
		pass
	display.windowHide("popup_menu")
	display.flush()
	detach_popup_menu_actions_from_buttons()
	return(menuitems[current_popup_selection])


def play_game(level, theme_in_game,sound_setting):

	def import_maze():
		nonlocal maze,direction,current_position_x,current_position_y, steps
		mazes=["",
		"http://www.bigorno.net/rt/#|1|,,,,,,,s,s,,,s,s,,,,,s,,,s,,,,,s,b1,i+i,b2,b2,,,,b1,,,j1,,s,s,,s,,s,s,i+i,,,,s,,,,s,,,t4+u,s,,,,,s,,|t:orig|",
		"http://www.bigorno.net/rt/#|1|,,,,j1,s,i+i,,,,,,s,i+i,b2,,,,,,i+i,,b1,,,,,,s,i+i,,,,,,,s,b1,,,,,,,s,,b2,s,,,,,s,,,s,,,,,s,,,t4+u,|t:orig|",
		"http://www.bigorno.net/rt/#|1|s,,i+i,s,,,,s,,,,,,b1,,,i+i,b2,s,s,s,s,,i+i,,,s,,j1,s,,,s,,s,,s,,,s,,,s,,i+i,s,,,s,,b2,,s,,b1,s,,,i+i,,,s,,t4+u,|t:orig|",
		"http://www.bigorno.net/rt/#|1|s,,,,,,,s,,i+i,,s,s,,,,,s,,s,j1,s,i+i,,,s,b2,s,,i+i,b2,s,,s,,,b1,s,i+i,,,s,i+i,s,,,s,,i+i,,s,s,s,,,,,,b1,i+i,,,s,t4+u,|t:orig|",
		"http://www.bigorno.net/rt/#|1|,,i+i,s,,,,i+i,,b1,,,s,,b2,,,s,,s,,,s,,,s,,s,s,,s,,,s,,b1,,,s,,,s,,,i+i,s,,,,,s,s,s,,i+i,b2,i+i,,,,j1,s,,t4+u,|t:orig|",
		"http://www.bigorno.net/rt/#|1|j1,s,,,,s,i+i,,,,s,,,,,b2,,,s,,s,s,,,,,s,,,s,,s,b1,s,i+i,,,s,,s,i+i,,b1,,s,s,b2,,s,s,i+i,s,,,i+i,,t4+r,,,,,s,,,|t:orig|",
		"http://www.bigorno.net/rt/#|1|,i+i,,,,,,,,,,s,s,s,,,s,b2,,s,j1,s,,i+i,,,s,i+i,b2,i+i,,s,i+i,,s,,,s,,i+i,s,,i+i,s,,s,,,,,s,i+i,b1,i+i,b1,s,,,,,,s,,t4+u,|t:orig|",
		"http://www.bigorno.net/rt/#|1|t4+d,,i+i,,,,i+i,,,i+i,s,i+i,s,s,s,,i+i,b1,i+i,b2,i+i,,,b1,s,,s,i+i,s,i+i,,,,,s,,,,s,s,b2,s,,s,s,s,,,,i+i,,s,,,i+i,s,,s,,,,s,,j1,|t:orig|",
		"http://www.bigorno.net/rt/#|1|,,s,i+i,,,,i+i,s,,,,s,s,,,,,s,,,i+i,s,,,s,s,,s,,,,,j1,s,b2,i+i,b2,s,,,s,i+i,b1,b1,,,s,,s,,s,i+i,s,,i+i,,s,,,,,,t4+u,|t:orig|",
		"http://www.bigorno.net/rt/#|1|j3,s,,,,s,i+i,,,s,,s,,,b1,,,,,s,s,s,,,,s,s,i+i,i+i,i+i,s,,s,,b2,,,,s,,i+i,b1,i+i,s,s,i+i,s,,,s,,s,,b2,i+i,,t4+r,,,,,i+i,s,,|t:orig|",
		"http://www.bigorno.net/rt/#|1|,,,,,,,,,s,,s,,s,,s,,s,i+i,s,i+i,s,i+i,s,,s,,,s,j1,b1,i+i,,s,,i+i,i+i,s,i+i,s,,s,i+i,s,b1,i+i,b2,i+i,,s,b2,,i+i,s,s,,t4+u,,i+i,s,,,,,|t:orig|",
		"http://www.bigorno.net/rt/#|1|,,,,,i+i,s,,,s,s,,,b2,i+i,s,,,s,,s,i+i,,j1,s,i+i,i+i,s,i+i,b2,b1,s,,,,,,,,i+i,,,s,s,s,,,,s,,,b1,,s,s,s,,,,s,,,,t1+u,|t:orig|"]

		mazeURL=mazes[level]
		mazeURL_useful_start=mazeURL.find("#")+4
		mazeURL_useful_end=mazeURL.find(",|t:")
		maze_temp=mazeURL[mazeURL_useful_start:mazeURL_useful_end].split(",")
		for y in range(10):
			for x in range(10):
				if x==0 or x==9 or y==0 or y==9:
					maze[x][y][0]="B"
					maze[x][y][1]=" "
				else:
					maze[x][y][0]=" "
					maze[x][y][1]=" "
					if maze_temp[(y-1)*8+(x-1)]=="s": maze[x][y][0]="B"
					elif maze_temp[(y-1)*8+(x-1)][:1]=="i":
						if maze_temp[(y-1)*8+(x-1)][2:]=="p": maze[x][y][0]="P"
						else: maze[x][y][0]="J"
					elif maze_temp[(y-1)*8+(x-1)]=="i+i": maze[x][y][0]="J"
					elif maze_temp[(y-1)*8+(x-1)][:1]=="j": maze[x][y][0]="K"
					elif maze_temp[(y-1)*8+(x-1)][:1]=="b": maze[x][y][1]="L"
					elif maze_temp[(y-1)*8+(x-1)][:1]=="t":
						if maze_temp[(y-1)*8+(x-1)][-1]=="u": direction=0
						elif maze_temp[(y-1)*8+(x-1)][-1]=="r": direction=1
						elif maze_temp[(y-1)*8+(x-1)][-1]=="d": direction=2
						elif maze_temp[(y-1)*8+(x-1)][-1]=="l": direction=3
						current_position_x=x
						current_position_y=y
						maze[x][y][1]=direction


	def display_maze(window, undo):
		display.windowShow(window)
		display.drawFill(window,background_color)
		if window=="game_board":
			field_size=16
		else:
			field_size=8

		for y in range(1,9):
			for x in range(1,9):
				if maze[x][y][1]==" ":
					if maze[x][y][0]!=" ":
						display.drawPng(window,(x-1)*field_size,(y-1)*field_size,"/lib/turtle_game/" + str(maze[x][y][0]).lower() + "_" + str(field_size) + "px_" + theme + ".png")
				else:
					display.drawPng(window,(x-1)*field_size,(y-1)*field_size,"/lib/turtle_game/" + str(maze[x][y][1]).lower() + "_" + str(field_size) + "px_" + theme + ".png")

		if window=="game_board":
			if (3 <= current_position_y <= 7) and (direction==0):
					display.windowMove("game_board",0,(current_position_y-3)*-16)
			elif (2 <= current_position_y <= 6) and (direction==2):
					display.windowMove("game_board",0,(current_position_y-2)*-16)
			elif current_position_y>6:
				display.windowMove("game_board",0,4*-16)
			elif current_position_y<3:
				display.windowMove("game_board",0,0)


		if window=="minimap":
			display.drawRect(window,0,0,int(display.width(window)/2),display.height(window),False,foreground_color)
			steps_string_prefix="No steps"
			steps_string=" taken "
			steps_string_postfix="yet."
			if steps>0:
				steps_string_prefix=str(steps) + " step"
				steps_string=" taken "
				steps_string_postfix="already."
			if steps>1:
				steps_string_prefix+="s"
			display_centered_message("minimap",96, 1, steps_string_prefix, foreground_color, myfont)
			display_centered_message("minimap",96, 14, steps_string, foreground_color, myfont)
			display_centered_message("minimap",96, 28, steps_string_postfix,foreground_color, myfont)


		display.drawRect(window,0,0,display.width(window),display.height(window),False,foreground_color)
		display.flush()

	def field_ahead(distance):
		nonlocal next_position_x, next_position_y
		position_x_temp=current_position_x
		position_y_temp=current_position_y
		if direction==0: position_y_temp=current_position_y - distance
		elif direction==1: position_x_temp=current_position_x + distance
		elif direction==2: position_y_temp=current_position_y + distance
		elif direction==3: position_x_temp=current_position_x - distance
		if maze[position_x_temp][position_y_temp][1]==" ":
			field_ahead=maze[position_x_temp][position_y_temp][0] 
		else:
			field_ahead=maze[position_x_temp][position_y_temp][1] 
		if distance==1:
			next_position_x=position_x_temp
			next_position_y=position_y_temp
		return field_ahead

	def action_happened(action_type):
		actions=["move","+","push","++","laser","*"]
		nonlocal myRegularCards
		myRegularCards[-1][1]=actions[actions.index(action_type)+1]

	def fire_laser(undo):
		nonlocal maze, myRegularCards
		if undo:
			if field_ahead(1)=="P" and myRegularCards[-1][1]=="*": maze[next_position_x][next_position_y][0] = "J"
		else:
			if field_ahead(1)=="J":
				action_happened("laser")
				maze[next_position_x][next_position_y][0] = "P"

	def turn_turtle(turn_direction, undo):
		nonlocal direction, maze
		if undo: turn_direction*=-1
		direction+=turn_direction
		if direction>3: direction=0
		elif direction<0: direction=3
		maze[current_position_x][current_position_y][1]=direction

	def move_ahead(undo):
		
		nonlocal diamond_found
		
		def make_move(position_x, position_y, object_type, undo):
			nonlocal maze, current_position_x, current_position_y
			movement=int()
			movement=-1 if undo else 1
			position_x_temp=position_x
			position_y_temp=position_y
			if direction==0: position_y_temp=position_y-1*movement
			if direction==1: position_x_temp=position_x+1*movement
			if direction==2: position_y_temp=position_y+1*movement
			if direction==3: position_x_temp=position_x-1*movement
			maze[position_x_temp][position_y_temp][1]=maze[position_x][position_y][1]
			maze[position_x][position_y][1]=" "
			if object_type.upper()=="T":
				current_position_x=position_x_temp
				current_position_y=position_y_temp
		
		if field_ahead(1)==" " or field_ahead(1)=="P":
			if not(undo):
				make_move(current_position_x, current_position_y, "t", undo)
				action_happened("move")
			else:
				if myRegularCards[-1][1]=="+":
					make_move(current_position_x, current_position_y, "t", undo)
				else:
					pass
		elif field_ahead(1)=="L":
			if not(undo):
				if field_ahead(2)==" " or field_ahead(2)=="P":
					make_move(next_position_x, next_position_y, "l", undo)
					make_move(current_position_x, current_position_y, "t", undo)
					action_happened("push")
			else:
				if myRegularCards[-1][1]=="+":
					make_move(current_position_x, current_position_y, "t", undo)
				if myRegularCards[-1][1]=="++":
					make_move(current_position_x, current_position_y, "t", undo)
					make_move(next_position_x, next_position_y, "l", undo)
		elif field_ahead(1)=="K":
			make_move(current_position_x,current_position_y,"t",False)
			action_happened("move")
			display_maze("game_board", undo)
			diamond_found=True
			if sound_on: play_sound("treasure found")
		elif field_ahead(1) in ("B","J","F"):
			if not(undo):
				pass
			else:
				if myRegularCards[-1][1]=="+":
					make_move(current_position_x,current_position_y,"t", undo)
		
		
	def process_card(card_type, undo):
		if card_type.upper()=="R":
			card=myRegularCards[-1][0]
		else:
			myFrogCards[-1][0]
		if card.upper()=="B": turn_turtle(-1, undo)
		elif card.upper()=="J": turn_turtle(1, undo)
		elif card.upper()=="E": move_ahead(undo)
		elif card.upper()=="L": fire_laser(undo)
		elif card.upper()=="F": pass
		

	def check_single_card(undo):
		process_card("r",undo)
		display_maze("game_board", undo)
		
	def insert_card(mydirection):
		nonlocal myRegularCards, steps
		if mydirection=="U":
			if len(myRegularCards)>0:
				check_single_card(True)
				myRegularCards.pop()
				steps-=1
		else:
			myRegularCards.append([mydirection,""])
			steps+=1
			check_single_card(False)

		
	def action_right(pressed):
		nonlocal multitouch_minimap, right_on
		if not pressed:
			badge.led(4,0,0,0)
			if not multitouch_minimap:
				insert_card("J")
				if sound_on: play_sound("turn right")
			right_on=False
		else:
			badge.led(4,1,0,1)
			right_on=True
			if up_on:
				multitouch_minimap=True
		
	def action_up(pressed):
		nonlocal multitouch_minimap, up_on		
		if not pressed:
			badge.led(1,0,0,0)
			if not multitouch_minimap:
				insert_card("E")
				if sound_on and not diamond_found: play_sound("move ahead")
			up_on=False
		else:
			badge.led(1,0,0,1)
			up_on=True
			if right_on:
				multitouch_minimap=True

	def action_left(pressed):
		nonlocal multitouch_exit, left_on, change
		change=True
		if not pressed:
			badge.led(4,0,0,0)
			if not multitouch_exit:
				insert_card("B")
				if sound_on: play_sound("turn left")
			left_on=False
		else:
			badge.led(4,1,1,0)
			left_on=True
			if down_on:
				multitouch_exit=True


	def action_down(pressed):
		nonlocal multitouch_exit, down_on, change
		change=True
		if not pressed:
			badge.led(1,0,0,0)	
			if not multitouch_exit:
				insert_card("U")
				if sound_on: play_sound("undo")
			down_on=False
		else:
			badge.led(1,1,1,1)
			down_on=True
			if left_on:
				multitouch_exit=True

		
	def action_enter(pressed):
		if not pressed:
			badge.led(3,0,0,0)
			insert_card("L")
			if sound_on: play_sound("fire laser")
		else:
			badge.led(3,1,0,0)

	def attach_gameplay_actions_to_buttons():
		buttons.attach(buttons.BTN_LEFT, action_left)
		buttons.attach(buttons.BTN_RIGHT, action_right)
		buttons.attach(buttons.BTN_UP, action_up)
		buttons.attach(buttons.BTN_DOWN, action_down)
		buttons.attach(buttons.BTN_OK, action_enter)
		
	def detach_gameplay_actions_from_buttons():
		buttons.detach(buttons.BTN_LEFT)
		buttons.detach(buttons.BTN_RIGHT)
		buttons.detach(buttons.BTN_UP)
		buttons.detach(buttons.BTN_DOWN)
		buttons.detach(buttons.BTN_OK)

	global sound_on
	
	maze=	[[["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""]],
				[["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""]],
				[["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""]],
				[["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""]],
				[["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""]],
				[["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""]],
				[["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""]],
				[["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""]],
				[["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""]],
				[["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""],["",""]]]

	steps=direction=current_position_x = current_position_y = next_position_x = next_position_y = 0
	myRegularCards=myFrogCards=list()
	left_on=down_on=right_on=up_on=multitouch_minimap=multitouch_exit=change=False
	diamond_found=False
	set_theme(theme_in_game)
	sound_on=sound_setting
	init_mywindow("game_board",128,128,0,0,True)
	init_mywindow("popup",96,48,16,8,True)
	init_mywindow("stepcounter",24,24,0,0,True)
	init_mywindow("minimap",128,64,0,0,True)
	init_mywindow("popup_menu",112,56,8,4,True)

	import_maze()
	attach_gameplay_actions_to_buttons()
	display_maze("game_board", False)
	while True:
		if not(left_on) and not(down_on) and multitouch_exit:
			multitouch_exit=False
			detach_gameplay_actions_from_buttons()
			if popup_menu("Exit level?",["Yes","No"],8,4,112,56,True)=="Yes":
				steps=-1
				break
			else:
				attach_gameplay_actions_to_buttons()

		if not(right_on) and not(up_on) and multitouch_minimap:
			multitouch_minimap=False
			detach_gameplay_actions_from_buttons()
			display_maze("minimap",False)
			popup_menu("",["Return"],65,46,62,17,False)
			display.windowHide("minimap")
			display_maze("game_board", False)
			attach_gameplay_actions_to_buttons()

		if diamond_found:
			popup_menu("Level completed\r\nin " + str(steps) + " steps.",["Ok"],8,4,112,56,True)
			break
	detach_gameplay_actions_from_buttons()
	display.windowHide("game_board")
	return steps

foreground_color=background_color=int()
myfont="pixelade13"
no_fill=0
fill=1
sound_on=False