''' Muster 8 Houdini Mantra IFD template class ''' 

''' Import Muster base modules '''
import MClientAPI
import MTemplateAPI
''' Import Python base lib modules '''
import os.path
import re
import shutil

''' Get the template manager singleton '''
manager = MTemplateAPI.MManager.getUniqueClass()

''' Define a new class derived from MTemplateAPI.MTemplate base class , override required methods '''
class NukeTemplate(MTemplateAPI.MTemplate):
	def __init__(self):
		MTemplateAPI.MTemplate.__init__(self)
		self.setID(821)
		self.setName("Nuke Workgroup")
		self.setDescription("Nuke Workgroup")
		self.setTemplateLogic(MTemplateAPI.kTemplateMultiframe)
		self.setDefaultPriority(1)
		self.setDefaultPools("")
		self.setDefaultExcludedPools("")
		self.setMaximumLicenses(0)
		self.setLicensesGroup("Arnold-licensing")
		self.setDelayGroup("Arnold")
		self.setDelay(0)
		self.setEnableAdditionalFlagsField(1)
		
		''' Multiframe template specific settings '''
		self.multiframe.setEnableFrameCheck(1)
		self.multiframe.setEnableMovieAssembler(1)
		self.multiframe.setCanProvideFramesMask(1)
			
		''' Submission form items allocation '''

		nukeFile = MTemplateAPI.MTemplateItemFile("NUKEFILENAME","Script file","Specify the Nuke script file","",0,1,1,"*.nk;*.*")
		startFrame = MTemplateAPI.MTemplateItemInteger("NUKESTARTFRAME","Start frame","Specifies the starting frame for the rendering job",1001,0,0,1)
		endFrame = MTemplateAPI.MTemplateItemInteger("NUKEENDFRAME","End frame","Specifies the ending frame for the rendering job",1100,0,0,1)
		stepFrame = MTemplateAPI.MTemplateItemInteger("NUKEBYFRAME","step frame","Specifies the ending frame for the rendering job",1,0,0,1)
		nukeScriptArgs = MTemplateAPI.MTemplateItemString("NUKESCRIPT","Script arguments","Specify script's argument to change (may be blank)","",0,0,0)
		renderThreads = MTemplateAPI.MTemplateItemInteger("NUKERENDERTHREADS","Threads","Specify the render threads",4,0,0,1)
		nukeVersion = MTemplateAPI.MTemplateItemString("NUKEVERSION","Nuke Version","Nuke Version","10.5v3",0,0,1)
		nukeExeVersion = MTemplateAPI.MTemplateItemString("NUKEEXEVERSION","Nuke Executable Name","Nuke Executable Name","Nuke10.5.exe",0,0,1)
		nukeCacheLimit = MTemplateAPI.MTemplateItemString("NUKECACHELIMIT","Ram Limit","Ram-Cache Limit","4096",0,0,0)
		nukePath = MTemplateAPI.MTemplateItemFolder("NUKEPATH","Nuke Path","Nuke Path","",0,0,1)
			
		self.addSubmissionItem(nukeFile)
		self.addSubmissionItem(startFrame)
		self.addSubmissionItem(endFrame)
		self.addSubmissionItem(stepFrame)
		self.addSubmissionItem(nukeScriptArgs)
		self.addSubmissionItem(renderThreads)
		self.addSubmissionItem(nukeVersion)
		self.addSubmissionItem(nukeExeVersion)
		self.addSubmissionItem(nukeCacheLimit)
		self.addSubmissionItem(nukePath)

		''' items mapping to Muster default tags '''
		self.addMapping("NUKEFILENAME","job_file")
		self.addMapping("NUKESTARTFRAME","start_frame")
		self.addMapping("NUKEENDFRAME","end_frame")
		self.addMapping("NUKEBYFRAME","by_frame")
		#self.addMapping("IFDOUTPUTPATH","output_folder")
		
		''' Additional flags '''
		customFlags = MTemplateAPI.MTemplateItemString("CUSTOM_FLAGS","Custom flags","Specify additional flags to concatenate to the command line","",1,0,0)
		self.addSubmissionAdditionalItem("Custom flags",customFlags)
	
		''' Windows support '''
		self.platformWindows.setPlatformEnabled(1)
		self.platformWindows.setEnableErrorCheck(1)
		self.platformWindows.setEnabledByDefault(1)
		self.platformWindows.setFramesFloating(0)
		self.platformWindows.setDetectionLogic(MTemplateAPI.kProcessChild)
		self.platformWindows.setDetectionLogicProcessName("Nuke.exe")
		#startingFolderPath = MTemplateAPI.MTemplateItemFolder("HOUDINIHOME","Houdini bin folder","Path to Houdini bin folder","C:\\Program Files\\Side Effects Software\\Houdini 13.0.547\\bin",0,0,1)
		#self.platformWindows.addClientConfigurationItem(startingFolderPath)
		
		''' OSX support '''
		self.platformOSX.setPlatformEnabled(0)

		''' Linux support '''
		self.platformLinux.setPlatformEnabled(0)

		
	''' virtual functions overrides '''	
	def onFieldChanged(self,  fieldName, fieldValue, fieldsToChange):
		''' Tell Console/web server to change the value of the project path and the frames destination with the values according '''
		#if fieldName == "NUKEFILENAME":
			#fieldsToChange.addEvent("NUKEFILENAME",MClientAPI.GetSequenceMask(fieldValue),MTemplateAPI.MTemplateItemEvent.kTemplateItemFieldsActivationNone)	

	def onBuildCommandLine(self, platform, job, chunk, clientTemplatePreferences,instanceNum):
		filePath = job.attributeGetString(manager.resolveMappingToJob(self.getID(),"NUKEFILENAME"))
		platform = MClientAPI.GetPlatform()
		if platform == MClientAPI.kPlatformWindows:
			pathToBat ="\"\\\\hades\\p\\env\\nuke\\_run\\Nuke\\Nuke" +  job.attributeGetString("NUKEVERSION") + "\\NukeFarm.bat\""
			# set detection logic process name
			self.platformWindows.setDetectionLogicProcessName(job.attributeGetString("NUKEEXEVERSION"))
			renderCmd = "/c "
			renderCmd += pathToBat + " "
			renderCmd += "-m " + str( job.attributeGetInt("NUKERENDERTHREADS")) + " "
			renderCmd += "-c " +  job.attributeGetString("NUKECACHELIMIT")  + "M" + " "
			renderCmd += job.attributeGetString("ADD_FLAGS") + " "
			renderCmd += filePath + " "
			renderCmd += "%.0f" % chunk.getStartFrame()
			renderCmd += "," + "%.0f" % chunk.getEndFrame()
			renderCmd += "," + "%.0f" % chunk.getByFrame()

			
		else:
			renderCmd = "-c \"cd ../ && source ./houdini_setup && cd bin && "
			renderCmd += "echo render -f "
			renderCmd += '%.0f' % chunk.getStartFrame()
			renderCmd += ' %.0f' % chunk.getEndFrame()
			renderCmd +=  job.attributeGetString("ADD_FLAGS")
			renderCmd += " -Va -s " 
			renderCmd += job.attributeGetString("HOUDINIOUTPUTDRIVER").replace(" ","\\ ")
			renderCmd += " | hbatch -R " + filePath.replace(" ","\\ ")  + "\""      
		return renderCmd
		
	def onBuildAdditionalParameters(self, attributes):
		renderCmd = ""
		if (attributes.isEnabled("CUSTOM_FLAGS")):
			renderCmd += attributes.getString("CUSTOM_FLAGS")
		return renderCmd

	def onBuildEnvironment(self, job, chunk, clientTemplatePreferences, existingEnvironment):
		environment = existingEnvironment
		
		environment.setValue("NUKE_PATH",job.attributeGetString("NUKEPATH"))
		environment.setValue("OFX_PLUGIN_PATH",job.attributeGetString("NUKEPATH") + "\\OFX")
		environment.setValue("LENSMODEL_PATH",job.attributeGetString("NUKEPATH") + "\\3delens")
		return environment

	def onGetApplicationPath(self, job,chunk, clientTemplatePreferences,pathOut):
		platform = MClientAPI.GetPlatform()
		if platform == MClientAPI.kPlatformWindows:
			#pathOut.setString(clientTemplatePreferences['HOUDINIHOME'] + "\\hcmd.exe")
			pathOut.setString("cmd.exe")
		else:
			pathOut.setString("/bin/sh")
		return MTemplateAPI.MTemplateError()
		
	def onGetApplicationStartingFolder(self, job, chunk, clientTemplatePreferences,pathOut):
		pathStart =  "c:\\Windows\\System32"
		platform = MClientAPI.GetPlatform()
		if platform == MClientAPI.kPlatformWindows:
			pathOut.setString(pathStart)
		else:
			pathOut.setString(clientTemplatePreferences['HOUDINIHOME'])
		return MTemplateAPI.MTemplateError()

	def onCheckForSubframeAdvancingString(self, job, chunk, line):
		return 0
		
	def onCheckForFramesMask(self,job,chunk,line,prefixOut):
		return 0

	def onCheckForSubframeProgress(self, job, chunk, line, progressOut):
		return 0
		
	def onCheckLogLine(self,job,chunk,clientTemplatePreferences,line,lineNum,warnings,errors,silencedWarnings,silencedErrors):
		return MTemplateAPI.MTemplateError()
		
	def onCheckLog(self,job,chunk,clientTemplatePreferences,log,warnings,errors,silencedWarnings,silencedErrors):
		## WARNINGS
		noWarnings = ["Warning: [kellerPluginCore]", "Warning: Creating writedir", "Warning: Autosave file for"]
		foundset = []
		
		for line in log.splitlines():
			if line.lower().find("warning") != -1:
				foundset.append(line)
		# remove no warning strings
		result = [x for x in foundset if not any(y in x for y in noWarnings)]
		if len(result) != 0:
			return MTemplateAPI.MTemplateError(2,"Warning keyword found",MTemplateAPI.MTemplateError.kTemplateErrorTypeWarning)
		## ERRORS
		if log.lower().find("error") != -1:
			return MTemplateAPI.MTemplateError(1,"Error keyword found",MTemplateAPI.MTemplateError.kTemplateErrorTypeError)
		if log.lower().find("no licenses could be found to run this application") != -1:
			return MTemplateAPI.MTemplateError(1,"No license available",MTemplateAPI.MTemplateError.kTemplateErrorTypeError)
		return MTemplateAPI.MTemplateError()
		
        
	def onCheckExitCode(self,job,chunk,clientTemplatePreferences,exitCode):
		if exitCode != 0:
			return MTemplateAPI.MTemplateError(exitCode, "Exit code %d different from expected 0 value" % exitCode,MTemplateAPI.MTemplateError.kTemplateErrorTypeWarning)
		
		return MTemplateAPI.MTemplateError()

	def onApplicationFinder(self,moduleRegExp,moduleTag):
		return MTemplateAPI.kTemplateScanNone
#		''' Search kick '''
#		moduleTag.setString("Houdini")
#		platform = MClientAPI.GetPlatform()
#		if platform == MClientAPI.kPlatformWindows:
#			moduleRegExp.setString("hcmd.exe")
#			return MTemplateAPI.kTemplateScanModule
#		else:
#			moduleRegExp.setString("hrender")
#			return MTemplateAPI.kTemplateScanModule
#		return MTemplateAPI.kTemplateScanNone
		
	def onFindApplication(self,basePath,clientTemplatePreferences):
		pass
		
	def onModuleFound(self,moduleExec,modulePath,clientTemplatePreferences):
		platform = MClientAPI.GetPlatform()
		basePath = modulePath.getString()
		clientTemplatePreferences["HOUDINIHOME"] = basePath
		return 1
		
''' Create an instance of the template class and install it into the template manager context '''
template = NukeTemplate()
manager.installPyTemplate(template)

