#########################################################################
# pglauncher - An unoffical Launcher for the "Project: Gorgon" game     #
# Copyright (C) 2014  Alexander Schlarb                                 #
#                                                                       #
# This program is free software: you can redistribute it and/or modify  #
# it under the terms of the GNU General Public License as published by  #
# the Free Software Foundation, either version 3 of the License, or     #
# (at your option) any later version.                                   #
#                                                                       #
# This program is distributed in the hope that it will be useful,       #
# but WITHOUT ANY WARRANTY; without even the implied warranty of        #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         #
# GNU General Public License for more details.                          #
#########################################################################

import os
import platform
import subprocess

class Launcher:
	@classmethod
	def is_applicable(cls, patcher):
		"""
		Return whether this launcher method will work on this platform
		"""
		return False
	
	
	def __init__(self, patcher, directory=None):
		self.patcher = patcher
		
		if directory:
			self.directory = directory
		else:
			self.directory = patcher.get_default_directory()
	
	def get_binary_path(self):
		"""
		Return the absolute path of the game binary
		
		@return {str}
		"""
		return os.path.join(self.directory, self.patcher.get_binary_name())
	
	def launch(self):
		raise NotImplementedError("Launcher() class may not be used directly")


class NativeLauncher(Launcher):
	"""
	Launcher that natively runs the game by executing it (**MAGIC**)
	"""
	def launch(self):
		binary_path = self.get_binary_path()
		
		# Set executable bits for owner, group and others if the corresponding read bits are set
		mode = os.stat(binary_path).st_mode & 0o777
		for i in range(0, 9, 3):
			if ((mode >> (i+2)) & 0o1) > 0: # Check if read bit is set in permission bit group
				mode |= (0o1 << i) # Set executable bit for permission bit group
		os.chmod(binary_path, mode) # Apply changes
		
		# Execute main game binary
		subprocess.call([binary_path])
	
	@classmethod
	def is_applicable(cls, patcher):
		return platform.system() == patcher.get_target_platform()


class WINELauncher(Launcher):
	"""
	Launcher that runs the game by invoking the WINE abstraction layer
	"""
	def launch(self):
		subprocess.call(["wine", self.get_binary_path()])
	
	@classmethod
	def is_applicable(cls, patcher):
		return platform.system() in ("Linux", "Darwin")


launchers = [NativeLauncher, WINELauncher]


def launch(patcher):
	for Launcher in launchers:
		if Launcher.is_applicable(patcher):
			launcher = Launcher(patcher)
			launcher.launch()
			return True
	
	return False
