#First command in program imports / sets up log, so loading can be profiled
import src.log as log

#Next command is the config file
import src.config as config

#Then the normal packages: system then local

import os
import sys
log.info(f"running under Python {sys.version_info[0]}.{sys.version_info[1]}.{sys.version_info[2]}")
if sys.version_info < ( 3, 11 ):
	#3.10 because of the `match` statement, 3.11 because of `typing.Self`
	sys.exit(
		"Marble Madness requires at least Python 3.11.  "+
		f"You appear to be using Python {sys.version_info[0]}.{sys.version_info[1]}.  Aborting."
	)

#"pip install pygame-ce"
with open( os.devnull, "w" ) as f:
	oldstdout=sys.stdout; sys.stdout=f; import pygame; sys.stdout=oldstdout

log.info("loaded pygame")

#"pip install PyOpenGL"
import OpenGL
if not config.is_debugging:
	OpenGL.ERROR_CHECKING = False #Disable error checks
#OpenGL.ERROR_ON_COPY = True #Disallow implicit slow copies TODO
from OpenGL.GL  import *
from OpenGL.GLU import *

log.info("loaded OpenGL")

#"pip install numpy"
try:
	import numpy as np
	if config.is_debugging: np.set_printoptions( linewidth=200 )
	log.info("loaded NumPy")
except ModuleNotFoundError:
	pass

import src.audio as audio
import src.display as display
import src.highscores as highscores
import src.main_menu as main_menu
import src.tkgui.tk_highscore_name as tk_highscore_name
import src.tkgui.tk_highscores as tk_highscores
import src.tkgui.tk_info as tk_info
import src.tkgui.tk_lvlselect as tk_lvlselect
import src.tkgui.tk_options as tk_options

import src.game.driver as game_driver
import src.game.render_lowlevel as game_render_lowlevel

log.info("loaded all user modules and dependencies")



def task_play():
	display.main_window_remake_as_gl_game()
	display.set_caption(config.CAPTION_PLAY)

	points = game_driver.main()
	if highscores.is_highscore(points):
		name = tk_highscore_name.main_gui()
		if name != "":
			highscores.insert_score( highscores.Score(name,points) )

	display.main_window_remake_as_gl_menu()

def task_options():
	display.set_caption(config.CAPTION_OPTIONS)
	tk_options.main_gui()

def task_highscores():
	display.set_caption(config.CAPTION_HIGHSCORES)
	tk_highscores.main_gui()

def task_info():
	display.set_caption(config.CAPTION_INFO)
	tk_info.main_gui()

def task_lvlselect():
	display.set_caption(config.CAPTION_LVLSELECT)
	return tk_lvlselect.main_gui()

def task_menu():
	while True:
		display.set_caption(config.CAPTION_MENU)
		task = main_menu.main()

		if   task == main_menu.MENU_QUIT:
			return
		elif task == main_menu.MENU_PLAY:
			task_play()
		else: #tkinter-based GUI
			if   task == main_menu.MENU_OPTIONS:
				task_options()
			elif task == main_menu.MENU_HIGHSCORES:
				task_highscores()
			elif task == main_menu.MENU_INFO:
				task_info()
			elif task == main_menu.MENU_LVLSELECT:
				lvl_num = task_lvlselect()
			else:
				assert False

			display.main_window_remake_as_gl_menu() #Remake window (settings might have changed)

			if task == main_menu.MENU_LVLSELECT:
				if lvl_num != -1:
					config.LEVEL_CURRENT = lvl_num
					task_play()

def main():
	pygame.font.init()
	log.info("initialized pygame font")
	pygame.mixer.init() #Note should come after display initialized
	log.info("initialized pygame mixer")

	config.load()
	#In case we're creating the file on this run, save it now so that it appears the user has
	#	something to edit in the event of a later failure.
	config.save()
	highscores.load()
	log.info("loaded or created config and highscores")

	audio.init()
	log.info("loaded audio")

	display.init_tkinter()
	display.set_caption(config.CAPTION_MENU)
	display.main_window_remake_as_gl_menu()
	log.info("initialized main window and display")

	log.info("initialization complete")

	task_menu()
	#task_play()
	#task_options()
	#task_highscores()
	#task_info()
	#task_lvlselect()

	log.info("deinitializing")

	game_render_lowlevel.ensure_deinit()

	audio.deinit()

	highscores.save()
	config.save()

	pygame.quit()

if __name__ == "__main__":
	main()
	#import cProfile; cProfile.run("main()",sort="tottime")

	log.info("exit")
