##
#   :namespace  cross3d.maya.external
#
#   :remarks    This class can be used even outside of Maya. It gives you info on where
#				Maya is installed, and allows you to run scripts in Maya.
#				To Access this class use: cross3d.external('maya')
#   
#   :author     mikeh
#   :author     Blur Studio
#   :date       09/10/14
#
#

import os
import re
import subprocess

from cross3d import Exceptions
from cross3d.constants import ScriptLanguage
from cross3d.abstract.external import External as AbstractExternal

class External(AbstractExternal):
	_hkeyBase = r'Software\Autodesk\Maya'
	# In case the software is installed but not used don't find it when not passing in a version
	_ignoredVersions = set(os.environ.get('CROSS3D_STUDIO_IGNORED_MAYA', '2015').split(','))
	# map years to version numbers. Maya doesnt use these anymore, add older versions if support is needed
	_yearForVersion = {}

	@classmethod
	def name(cls):
		return 'Maya'

	@classmethod
	def runScript(cls, script, version=None, architecture=64, language=ScriptLanguage.Python, debug=False, headless=True):

		# If the script argument is a path to a file.
		if os.path.exists(script):

			# If the language is MEL we just use the script as is.
			if language == ScriptLanguage.MEL:
				scriptPath = script

			# If the language is Python we parse the file to get the content.
			elif language == ScriptLanguage.Python:
				with open(script, 'r') as fle:
					script = fle.read()

		if language == ScriptLanguage.Python:
			scriptTemplate = os.path.join(os.path.dirname(__file__), 'templates', 'external_python_script.meltempl')
			pythonScritpPath = os.path.splitext(cls.scriptPath())[0] + '.py'

			with open(pythonScritpPath, 'w') as fle:
				fle.write(script)

			with open(scriptTemplate) as fle:
				script = fle.read().format(debug=unicode(debug).lower())
				
			scriptPath = os.path.splitext(cls.scriptPath())[0] + '.mel'
			logPath = os.path.splitext(cls.scriptPath())[0] + '.log'
			with open(scriptPath, "w") as fle:
				fle.write(script)

		#--------------------------------------------------------------------------------
		# Developer's note: When running headless, these three messages are to be expected
		# I did my testing in Maya 2015 with Bonus Tools installed. The first two lines are because
		# bifrost doesn't properly check if it is in mayabatch mode. The third is because a script
		# in Bonus Tools also does not check if its in mayabatch mode.
		#--------------------------------------------------------------------------------
		# 1 error generated.
		# Error while processing C:\Program Files\Autodesk\Maya2015\plug-ins\bifrost\db\presets\__rootincludeall__.h.
		# Error: file: C:/ProgramData/Autodesk/ApplicationPlugins/MayaBonusTools/Contents/scripts-2015/bonusToolsMenu.mel line 1546: UI commands can't be run in batch mode.
		#--------------------------------------------------------------------------------

		binary = os.path.join(cls.binariesPath(version, architecture), 'mayabatch.exe' if headless else 'maya.exe')
		args = [binary, '-script', scriptPath, '-log', logPath]
		if debug and headless:
			# run mayabatch inside a cmd.exe prompt so you can see the output of mayabatch
			args = ['cmd.exe', '/k'] + args
		process = subprocess.Popen(args, creationflags=subprocess.CREATE_NEW_CONSOLE, env=os.environ)

		# TODO: Need to figure out a way to return False if the script has failed.
		return True

	@classmethod
	def binariesPath(cls, version=None, architecture=64, language='English'):
		""" Finds the install path for various software installations.
		:param version: The version of the software. Default is None
		:param architecture: The bit type to query the registry for(32, 64). Default is 64
		:param language: Optional language that may be required for specific softwares.
		"""
		def buildHKey(version):
			return r'{hkeyBase}\{version}\Setup\InstallPath'.format(hkeyBase=cls._hkeyBase, version=version)
		version = cls._yearForVersion.get(unicode(version), version)
		hive = 'HKEY_LOCAL_MACHINE'
		valueName = 'MAYA_INSTALL_LOCATION'
		ret = None
		from cross3d.migrate import winregistry
		if version == None:
			# Get all of the installed versions so we can find the latest version.
			versions = winregistry.listRegKeys(hive, cls._hkeyBase, architecture=architecture)
			for v in sorted(versions, reverse=True):
				if v not in cls._ignoredVersions:
					hkey = buildHKey(v)
					try:
						ret = winregistry.registryValue(hive, hkey, valueName, architecture)[0]
					except WindowsError:
						continue
					if ret:
						version = v
						break
		else:
			hkey = buildHKey(version)
			try:
				ret = winregistry.registryValue(hive, hkey, valueName, architecture)[0]
			except WindowsError:
				raise Exceptions.SoftwareNotInstalled('Maya', version=version, architecture=architecture, language=language)
		# If the version is not installed this will return '.', we want to return False.
		if ret:
			return os.path.join(os.path.normpath(ret), 'bin')
		raise Exceptions.SoftwareNotInstalled('Maya', version=version, architecture=architecture, language=language)