import distutils.sysconfig
import getopt
import glob
import os
import platform
import shutil
import subprocess
import stat
import sys
sys.path.append(os.path.join("..", "ScintillaEdit"))
import WidgetGen
scintillaDirectory = "../.."
scintillaScriptsDirectory = os.path.join(scintillaDirectory, "scripts")
sys.path.append(scintillaScriptsDirectory)
from FileGenerator import GenerateFile
# Decide up front which platform, treat anything other than Windows or OS X as Linux
PLAT_WINDOWS = platform.system() == "Windows"
PLAT_DARWIN = platform.system() == "Darwin"
PLAT_LINUX = not (PLAT_DARWIN or PLAT_WINDOWS)
def IsFileNewer(name1, name2):
	""" Returns whether file with name1 is newer than file with name2.  Returns 1
	if name2 doesn't exist. """
	if not os.path.exists(name1):
		return 0
	if not os.path.exists(name2):
		return 1
	mod_time1 = os.stat(name1)[stat.ST_MTIME]
	mod_time2 = os.stat(name2)[stat.ST_MTIME]
	return (mod_time1 > mod_time2)
def textFromRun(args):
	(stdoutdata, stderrdata) = subprocess.Popen(args, shell=True, stdout=subprocess.PIPE).communicate()
	return stdoutdata
def runProgram(args, exitOnFailure):
	print(" ".join(args))
	retcode = subprocess.call(" ".join(args), shell=True, stderr=subprocess.STDOUT)
	if retcode:
		print("Failed in " + " ".join(args) + " return code = " + str(retcode))
		if exitOnFailure:
			sys.exit()
def usage():
	print("sepbuild.py [-h|--help][-c|--clean][-u|--underscore-names]")
	print("")
	print("Generate PySide wappers and build them.")
	print("")
	print("options:")
	print("")
	print("-c --clean remove all object and generated files")
	print("-b --pyside-base  Location of the PySide+Qt4 sandbox to use")
	print("-h --help  display this text")
	print("-d --debug=yes|no  force debug build (or non-debug build)")
	print("-u --underscore-names  use method_names consistent with GTK+ standards")
modifyFunctionElement = """		%s
		"""
injectCode = """
			%s
			"""
injectCheckN = """
				if (!cppArg%d) {
					PyErr_SetString(PyExc_ValueError, "Null string argument");
					return 0;
				}"""
def methodSignature(name, v, options):
	argTypes = ""
	p1Type = WidgetGen.cppAlias(v["Param1Type"])
	if p1Type == "int":
		p1Type = "sptr_t"
	if p1Type:
		argTypes = argTypes + p1Type
	p2Type = WidgetGen.cppAlias(v["Param2Type"])
	if p2Type == "int":
		p2Type = "sptr_t"
	if p2Type and v["Param2Type"] != "stringresult":
		if p1Type:
			argTypes = argTypes + ", "
		argTypes = argTypes + p2Type
	methodName = WidgetGen.normalisedName(name, options, v["FeatureType"])
	constDeclarator = " const" if v["FeatureType"] == "get" else ""
	return methodName + "(" + argTypes + ")" + constDeclarator
def printTypeSystemFile(f, options):
	out = []
	for name in f.order:
		v = f.features[name]
		if v["Category"] != "Deprecated":
			feat = v["FeatureType"]
			if feat in ["fun", "get", "set"]:
				checks = ""
				if v["Param1Type"] == "string":
					checks = checks + (injectCheckN % 0)
				if v["Param2Type"] == "string":
					if v["Param1Type"] == "":	# Only arg 2 -> treat as first
						checks = checks + (injectCheckN % 0)
					else:
						checks = checks + (injectCheckN % 1)
				if checks:
					inject = injectCode % checks
					out.append(modifyFunctionElement % (methodSignature(name, v, options), inject))
				#if v["Param1Type"] == "string":
				#	out.append("" + name + "\n")
	return out
def doubleBackSlashes(s):
	# Quote backslashes so qmake does not produce warnings
	return s.replace("\\", "\\\\")
class SepBuilder:
	def __init__(self):
		# Discover configuration parameters
		self.ScintillaEditIncludes = [".", "../ScintillaEdit", "../ScintillaEditBase", "../../include"]
		if PLAT_WINDOWS:
			self.MakeCommand = "nmake"
			self.MakeTarget = "release"
		else:
			self.MakeCommand = "make"
			self.MakeTarget = ""
		if PLAT_DARWIN:
			self.QMakeOptions = "-spec macx-g++"
		else:
			self.QMakeOptions = ""
		# Default to debug build if running in a debug build interpreter
		self.DebugBuild = hasattr(sys, 'getobjects')
		# Python
		self.PyVersion = "%d.%d" % sys.version_info[:2]
		self.PyVersionSuffix = distutils.sysconfig.get_config_var("VERSION")
		self.PyIncludes = distutils.sysconfig.get_python_inc()
		self.PyPrefix = distutils.sysconfig.get_config_var("prefix")
		self.PyLibDir = distutils.sysconfig.get_config_var(
			("LIBDEST" if sys.platform == 'win32' else "LIBDIR"))
		# Scintilla
		with open("../../version.txt") as f:
			version = f.read()
			self.ScintillaVersion = version[0] + '.' + version[1] + '.' + version[2]
		# Find out what qmake is called
		self.QMakeCommand = "qmake"
		if not PLAT_WINDOWS:
			# On Unix qmake may not be present but qmake-qt4 may be so check
			pathToQMake = textFromRun("which qmake-qt4 || which qmake").rstrip()
			self.QMakeCommand = os.path.basename(pathToQMake)
		# Qt default location from qmake
		self._SetQtIncludeBase(textFromRun(self.QMakeCommand + " -query QT_INSTALL_HEADERS").rstrip())
		# PySide default location
		# No standard for installing PySide development headers and libs on Windows so
		# choose /usr to be like Linux
		self._setPySideBase('\\usr' if PLAT_WINDOWS else '/usr')
		self.ProInclude = "sepbuild.pri"
		self.qtStyleInterface = True
	def _setPySideBase(self, base):
		
		self.PySideBase = base
		if PLAT_LINUX:
			self.PySideTypeSystem = textFromRun("pkg-config --variable=typesystemdir pyside").rstrip()
			self.PySideIncludeBase = textFromRun("pkg-config --variable=includedir pyside").rstrip()
			self.ShibokenIncludeBase = textFromRun("pkg-config --variable=includedir shiboken").rstrip()
		else:
			self.PySideTypeSystem = os.path.join(self.PySideBase, "share", "PySide", "typesystems")
			self.ShibokenIncludeBase = os.path.join(self.PySideBase, "include", "shiboken")
			self.PySideIncludeBase = os.path.join(self.PySideBase, "include", "PySide")
		self.PySideIncludes = [
			self.ShibokenIncludeBase,
			self.PySideIncludeBase,
			os.path.join(self.PySideIncludeBase, "QtCore"),
			os.path.join(self.PySideIncludeBase, "QtGui")]
		self.PySideLibDir = os.path.join(self.PySideBase, "lib")
		self.AllIncludes = os.pathsep.join(self.QtIncludes + self.ScintillaEditIncludes + self.PySideIncludes)
		self.ShibokenGenerator = "shiboken"
		# Is this still needed? It doesn't work with latest shiboken sources
		#if PLAT_DARWIN:
		#	# On OS X, can not automatically find Shiboken dylib so provide a full path
		#	self.ShibokenGenerator = os.path.join(self.PySideLibDir, "generatorrunner", "shiboken")
	def generateAPI(self, args):
		os.chdir(os.path.join("..", "ScintillaEdit"))
		if not self.qtStyleInterface:
			args.insert(0, '--underscore-names')
		WidgetGen.main(args)
		f = WidgetGen.readInterface(False)
		os.chdir(os.path.join("..", "ScintillaEditPy"))
		options = {"qtStyle": self.qtStyleInterface}
		GenerateFile("typesystem_ScintillaEdit.xml.template", "typesystem_ScintillaEdit.xml", 
			"