''' Muster 8 Nuke 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(40)
		self.setName("Nuke")
		self.setIconFilename("nuke.png")
		self.setDescription("Nuke render")
		self.setTemplateLogic(MTemplateAPI.kTemplateMultiframe)
		self.setDefaultPriority(1)
		self.setDefaultPools("")
		self.setDefaultExcludedPools("")
		self.setMaximumLicenses(0)
		self.setLicensesGroup("Nuke-licensing")
		self.setDelayGroup("Nuke")
		self.setDelay(0)
		self.setEnableAdditionalFlagsField(True)
		
		''' Multiframe template specific settings '''
		self.multiframe.setEnableFrameCheck(True)
		self.multiframe.setEnableMovieAssembler(True)
		self.multiframe.setCanProvideFramesMask(False)
		self.multiframe.setSupportsRenderLayerFlag(False)
		
		''' Submission form items allocation '''
		nukeFile = MTemplateAPI.MTemplateItemFile("NUKEFILENAME","Scene file","Specifies the Nuke scene file to render","",0,1,1,"*.nk")
		nukeFrames = MTemplateAPI.MTemplateItemFramesRange("NUKEFRAMES","Frames","Specifies the frames ranges for the rendering job in the 1-10x1s1n1,... form","1-10",0,0,1)
		
		self.addSubmissionItem(nukeFile)
		self.addSubmissionItem(nukeFrames)
		
		''' items mapping to Muster default tags '''
		self.addMapping("NUKEFRAMES","frames_range")
		self.addMapping("NUKEFILENAME","job_file")
	
		''' 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(True)
		self.platformWindows.setEnableErrorCheck(True)
		self.platformWindows.setEnabledByDefault(True)
		self.platformWindows.setFramesFloating(0)
		self.platformWindows.setDetectionLogic(MTemplateAPI.kProcessDirect)
		startingFolderPath = MTemplateAPI.MTemplateItemFolder("NUKEHOME","Nuke root folder","Path to Nuke executable root folder","C:\\program files\\Nuke6.0v5",0,0,1)
		executablePath = MTemplateAPI.MTemplateItemFile("NUKEAPP","Nuke batch executable","Path to Nuke executable","C:\\program files\\Nuke6.0v5\\Nuke6.0v5",0,0,1,"*.exe")
		
		self.platformWindows.addClientConfigurationItem(startingFolderPath)
		self.platformWindows.addClientConfigurationItem(executablePath)
		
		''' OSX support '''
		self.platformOSX.setPlatformEnabled(True)
		self.platformOSX.setEnableErrorCheck(True)
		self.platformOSX.setEnabledByDefault(True)
		self.platformOSX.setFramesFloating(0)
		self.platformOSX.setDetectionLogic(MTemplateAPI.kProcessDirect)
		startingFolderPath = MTemplateAPI.MTemplateItemFolder("NUKEHOME","Nuke root folder","Path to Nuke executable root folder","/usr/local/Nuke6.0v5/Nuke6.0v5.app",0,0,1)
		executablePath = MTemplateAPI.MTemplateItemFile("NUKEAPP","Nuke batch executable","Path to Nuke executable","/usr/local/Nuke6.0v5/Nuke6.0v5.app/Nuke6.0v5",0,0,1,"*")
		self.platformOSX.addClientConfigurationItem(startingFolderPath)
		self.platformOSX.addClientConfigurationItem(executablePath)

		''' Linux support '''
		self.platformLinux.setPlatformEnabled(True)
		self.platformLinux.setEnableErrorCheck(True)
		self.platformLinux.setEnabledByDefault(True)
		self.platformLinux.setFramesFloating(0)
		self.platformLinux.setDetectionLogic(MTemplateAPI.kProcessDirect)
		startingFolderPath = MTemplateAPI.MTemplateItemFolder("NUKEHOME","Nuke root folder","Path to Nuke executable root folder","/usr/local/Nuke6.0v5",0,0,1)
		executablePath = MTemplateAPI.MTemplateItemFile("NUKEAPP","Nuke batch executable","Path to Nuke executable","/usr/local/Nuke6.0v5/Nuke6.0v5",0,0,1,"*")
		self.platformLinux.addClientConfigurationItem(startingFolderPath)
		self.platformLinux.addClientConfigurationItem(executablePath)
		
		
	''' virtual functions overrides '''
		
	def onBuildCommandLine(self, platform, job, chunk, clientTemplatePreferences,instanceNum):
		renderCmd = "-V " + job.attributeGetString("ADD_FLAGS")
		renderCmd += " -F " + '%.0f' % chunk.getStartFrame()
		renderCmd += "-" + '%.0f' % chunk.getEndFrame()
		renderCmd += "x" + '%.0f' % chunk.getByFrame()
		renderCmd += " -x \"" + job.attributeGetString(manager.resolveMappingToJob(self.getID(),"NUKEFILENAME")) + "\""
		return renderCmd
		
	def onBuildAdditionalParameters(self, attributes):
		renderCmd = ""
		if (attributes.isEnabled("CUSTOM_FLAGS")):
			renderCmd += attributes.getString("CUSTOM_FLAGS")
		return renderCmd
		
	def onGetApplicationPath(self,job,chunk,clientTemplatePreferences,pathOut ):
		pathOut.setString(clientTemplatePreferences['NUKEAPP'])
		return MTemplateAPI.MTemplateError()
		
	def onGetApplicationStartingFolder(self,job,chunk,clientTemplatePreferences,pathOut):
		pathOut.setString(clientTemplatePreferences['NUKEHOME'])
		return MTemplateAPI.MTemplateError()
		
	def onCheckForSubframeAdvancingString(self,job,chunk,line):
		return 0

	def onCheckForSubframeProgress(self,job,chunk,line, progressOut):
		return 0

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

	def onGetFlagForRenderLayers(self,job,layers):
		return ""
		
	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):
		lines = log.split("\n")
		
		for idx, val in enumerate(lines):
			marker = manager.checkForLineParsingOverrides(job,chunk,val,idx)
			if marker.getType() == MClientAPI.MTextFileMarker.kFileMarkerError:
				errors.append(marker)
			elif marker.getType() == MClientAPI.MTextFileMarker.kFileMarkerWarning:
				warnings.append(marker)
			elif marker.getType() == MClientAPI.MTextFileMarker.kFileMarkerSilenceError:
				''' The builtin parser has a skip rule for this line, do not include it in the warnings/errors but in the silenced errors'''
				silencedErrors.append(marker)
			elif marker.getType() == MClientAPI.MTextFileMarker.kFileMarkerSilenceWarning:
				''' The builtin parser has a skip rule for this line, do not include it in the warnings/errors but in the silenced warnings'''
				silencedWarnings.append(marker)
			else:
				''' We have no fixed rule , parse the line according to the template logic '''
				baseError = -1
				baseWarning = -1
				length = -1
				baseError = val.lower().find("error")
				baseWarning = val.lower().find("warning")
				
				if baseError != -1:
					length = len(val)-baseError;
					marker = MClientAPI.MTextFileMarker(MClientAPI.MTextFileMarker.kFileMarkerError,idx,baseError,length)
					errors.append(marker)
				if baseWarning != -1:
					length = len(val)-baseWarning;
					marker = MClientAPI.MTextFileMarker(MClientAPI.MTextFileMarker.kFileMarkerWarning,idx,baseWarning,length)
					warnings.append(marker)
			
		if len(errors) > 0 and len(warnings) > 0:
			return MTemplateAPI.MTemplateError(2,"Errors and warnings reported in the log. Please check the chunk details for a detailed list",MTemplateAPI.MTemplateError.kTemplateErrorTypeError)
		elif len(errors) > 0:
			return MTemplateAPI.MTemplateError(2,"Errors reported in the log. Please check the chunk details for a detailed list",MTemplateAPI.MTemplateError.kTemplateErrorTypeError)
		elif len(warnings) > 0:
			return MTemplateAPI.MTemplateError(1,"Warning reported in the log. Please check the chunk details for a detailed list",MTemplateAPI.MTemplateError.kTemplateErrorTypeWarning)
	
		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):
		''' Search nuke '''
		moduleTag.setString("Nuke")
		platform = MClientAPI.GetPlatform()
		moduleRegExp.setString("Nuke\d+\.\dv\d+.*?")
		return MTemplateAPI.kTemplateScanModule
		
	def onFindApplication(self,basePath,clientTemplatePreferences):
		pass
		
	def onModuleFound(self,moduleExec,modulePath,clientTemplatePreferences):
		platform = MClientAPI.GetPlatform()
		basePath = modulePath.getString()
		baseModule = moduleExec.getString()
		clientTemplatePreferences["NUKEHOME"] = basePath
		clientTemplatePreferences["NUKEAPP"] = os.path.join(basePath ,baseModule)
		return 1
		
''' Create an instance of the template class and install it into the template manager context '''
template = NukeTemplate()
manager.installPyTemplate(template)
