################################################################
#
#   Bell Runner - Shell
#
################################################################

import os, sys
from albow.shell import Shell
from albow.dialogs import alert, ask
from albow.file_dialogs import request_old_filename, request_new_filename
from game import game
from about_screen import AboutScreen
from main_menu_screen import MainMenuScreen
from play_screen import PlayScreen
from edit_menu_screen import EditMenuScreen
from editor_screen import EditorScreen
import settings

class BRShell(Shell):

	bg_color = (224, 224, 224)
	
	previous_screen = None

	def __init__(self, display):
		Shell.__init__(self, display)
		self.redraw_every_frame = False
		self.set_timer(settings.frame_time)
		self.about_screen = AboutScreen(self)
		self.menu_screen = MainMenuScreen(self)
		self.play_screen = PlayScreen(self)
		self.edit_menu_screen = EditMenuScreen(self)
		self.editor_screen = EditorScreen(self)
		options = settings.options
		self.show_menu_screen()
		if options.filename:
			if self.load_file(os.path.abspath(options.filename)):
				if options.edit:
					self.edit_level()
				else:
					self.restart_level()
		elif options.edit:
			self.new_level()
			self.edit_level()
		elif options.newgame:
			self.new_game()
	
	def show_about_screen(self):
		if self.current_screen is not self.about_screen:
			self.previous_screen = self.current_screen
			self.show_screen(self.about_screen)

	def show_menu_screen(self):
		self.show_screen(self.menu_screen)

	def show_play_screen(self, testing = False):
		if game.level:
			game.testing = testing
			self.show_screen(self.play_screen)
		else:
			self.show_menu_screen()
	
	def show_edit_menu_screen(self):
		self.show_screen(self.edit_menu_screen)
	
	def show_editor_screen(self):
		if game.level:
			self.show_screen(self.editor_screen)
		else:
			self.show_edit_menu_screen()
	
	def show_previous_screen(self):
		self.show_screen(self.previous_screen or self.main_menu_screen)
	
	def load_file(self, path):
		if path.endswith(settings.level_set_suffix):
			return self.load_level_set(path)
		elif path.endswith(settings.level_file_suffix):
			return self.load_level_file(path)
		elif path.endswith(settings.save_file_suffix):
			return self.load_game_file(path)
		return False
	
	def about(self):
		self.show_about_screen()
	
	def new_game(self):
		if self.ask_save():
			game.new_game()
			if game.level:
				self.restart_level()
			else:
				alert("No levels found.")
				self.show_menu_screen()
	
	def load_game(self):
		if self.ask_save():
			dir = game.get_save_dir()
			path = request_old_filename(suffixes = [settings.save_file_suffix],
				directory = dir)
			if path:
				self.load_game_file(path)
	
	def load_game_file(self, path):
		try:
			game.load_game(path)
			self.restart_level()
		except EnvironmentError, e:
			alert("Unable to load '%s': %s" % (
				os.path.basename(path), e))
	
	def save_game_enabled(self):
		return game.game_in_progress()

	def save_game(self):
		old_path = game.get_save_path()
		new_path = request_new_filename(prompt = "Save game as:",
			suffix = settings.save_file_suffix, pathname = old_path)
		if new_path:
			try:
				game.save_game(new_path)
				return True
			except EnvironmentError, e:
				alert("Unable to save '%s': %s" % (
					os.path.basename(new_path), mess))
		return False
	
	def resume_game_enabled(self):
		return game.level_in_progress()

	def resume_game(self):
		if game.level:
			self.show_play_screen()
	
	def restart_level_enabled(self):
		return game.level is not None
	
	def restart_level(self):
		game.level.reset()
		self.show_play_screen()
	
	def test_level_enabled(self):
		return game.level is not None
	
	def test_level(self):
		game.level.reset()
		self.show_play_screen(testing = True)
	
	def play_next_level(self):
		if self.ask_save_level():
			game.load_next_uncompleted_level()
			if game.level:
				self.restart_level()
			else:
				self.show_menu_screen()
		else:
			self.show_editor_screen()
	
	def open_level_set(self):
		if self.ask_save():
			path = request_old_filename(suffixes = [settings.level_set_suffix],
				directory = game.get_default_level_set_dir())
			if path:
				if self.load_level_set(path):
					self.restart_level()
	
	def load_level_set(self, path):
		game.set_level_set_path(path)
		try:
			game.new_game()
		except EnvironmentError, e:
			alert("Unable to load first level of '%s': %s" % (
				os.path.basename(path), e))
			return False
		if not game.level:
			alert("No levels found.")
			return False
		return True

	def enter_level_editor(self):
		self.show_edit_menu_screen()
	
	def create_level_set(self):
		path = request_new_filename(prompt = "Create level set named:",
			suffix = settings.level_set_suffix,
			directory = game.get_default_level_set_dir(),
			filename = "CustomLevels")
		if path:
			name = os.path.basename(path)
			try:
				os.mkdir(path)
			except EnvironmentError, e:
				alert("Unable to create '%s': %s:" % (name, e))
				return
		game.set_level_set_path(path)
		alert("Level set '%s' created." % name)
	
	def new_level(self):
		if self.ask_save():
			game.new_level()
			self.show_editor_screen()
	
	def open_level(self):
		path = request_old_filename(suffixes = [settings.level_file_suffix],
			directory = game.get_default_level_dir())
		if path:
			if self.load_level_file(path):
					self.show_editor_screen()
					return True
		return False
	
	def load_level_file(self, path):
		try:
			game.load_level(path)
			return True
		except EnvironmentError, e:
			alert("Unable to load '%s': %s" % (
				os.path.basename(path), e))
		return False
	
	def save_level(self):
		return self.write_level(ask_path = False)
	
	def save_level_as(self):
		return self.write_level(ask_path = True)
	
	def write_level(self, ask_path):
		path = game.get_level_path()
		if not path or ask_path:
			if path:
				dir, name = os.path.split(path)
			else:
				dir = game.get_default_level_dir()
				name = None
			path = request_new_filename(prompt = "Save level as:",
				suffix = settings.level_file_suffix, directory = dir, filename = name)
		if not path:
			return False
		try:
			game.write_level(path)
			game.level_needs_saving = False
			return True
		except EnvironmentError, e:
			alert("Unable to save '%s': %s" % (
					os.path.basename(path), mess))
		return False
	
	def edit_level_enabled(self):
		return game.level is not None
	
	def edit_level(self):
		game.level.reset()
		self.show_editor_screen()
	
	def exit_level_editor(self):
		self.show_menu_screen()
	
	def ask_save(self):
		return self.ask_save_progress() and self.ask_save_level()
		
	def ask_save_progress(self):
		if game.unsaved_progress:
			resp = ask("Save game progress?", ["Yes", "No", "Cancel"])
			if resp == "Cancel":
				return False
			if resp == "Yes":
				if not self.save_game():
					return False
		return True
	
	def ask_save_level(self):
		if game.level_needs_saving:
			resp = ask("Save changes to level?", ["Yes", "No", "Cancel"])
			if resp == "Cancel":
				return False
			if resp == "Yes":
				if not self.save_level():
					return False
		return True

	def confirm_quit(self):
		return self.ask_quit() and self.ask_save()
	
	def ask_quit(self):
		return ask("Quit the game?") == "OK"

	def begin_frame(self):
		#game.begin_frame()
		screen = self.current_screen
		if screen:
			screen.begin_frame()
