import nuke, colorsys, operator, sys


def IBKstacker():
	# GROUP BEGIN
	#
	# the start of the group
	# nGroup --> the name of the group variable that will house the script
	nGroup = nuke.nodes.Group()
	nGroup.setName("IBKStacker_IS")
	nGroup.knob("tile_color").setValue(10027263)
	nGroup.begin()


	# KNOBS AND SLIDERS
	#
	# k_screenType --> user selected screen type for the stack, blue or green
	# k_size --> user selected size for the stack, best left at 1
	# k_darks --> user selected darks for the stack
	# k_lights --> user selected lights for the stack
	# k_erode --> user selected erode value for the main IBKColour, other IBKColour nodes will have an erode value of 0
	# k_numStacks --> the desired number of stacks, increasing the stack value with create a new IBKColour with an exponentially increasing patch black value
	# k_patchBlack --> user selected patch black value for the main IBKColour node, best left at 0
	# k_expand --> a checkbox that will expand the group to the main node graph
	screenTypeItems = ["green", "blue"]
	k_screenType = nuke.Enumeration_Knob("screenType", "screen type", screenTypeItems)
	k_screenType.setValue(1)
	nGroup.addKnob(k_screenType)

	k_size = nuke.Double_Knob("size", "size")
	k_size.setRange(0,100)
	k_size.setValue(1)
	nGroup.addKnob(k_size)

	k_darks = nuke.Color_Knob("darks", "darks")
	nGroup.addKnob(k_darks)

	k_lights = nuke.Color_Knob("lights", "lights")
	lightsDefault = ["1","1","1"]
	k_lights.setValue(lightsDefault)
	nGroup.addKnob(k_lights)

	k_divider01 = nuke.Text_Knob("divider","")
	nGroup.addKnob(k_divider01)

	k_erode = nuke.Double_Knob("erode", "erode")
	k_erode.setRange(0,5)
	nGroup.addKnob(k_erode)

	k_divider02 = nuke.Text_Knob("divider","")
	nGroup.addKnob(k_divider02)

	k_patchBlack = nuke.Double_Knob("patchBlack", "patch black")
	k_patchBlack.setRange(0,5)
	nGroup.addKnob(k_patchBlack)

	k_divider03 = nuke.Text_Knob("divider","")
	nGroup.addKnob(k_divider03)

	k_numStacks = nuke.Int_Knob("numStacks", "stack size")
	nGroup.addKnob(k_numStacks)

	k_divider04 = nuke.Text_Knob("divider","")
	nGroup.addKnob(k_divider04)

	k_expand = nuke.Boolean_Knob("expand", "expand group")
	nGroup.addKnob(k_expand)



	# NODES
	#
	# nInput --> the input of the group node
	# nIBK_main --> the topmost IBKColour node in the stack, controls the values of all other nodes in the stack
	# nOutput --> the output of the group node
	nInput = nuke.nodes.Input()

	nIBK_main = nuke.nodes.IBKColourV3(name = "IBK00", Size = str(k_size.value()))
	nIBK_main.setInput(0, nInput)

	nOutput = nuke.nodes.Output()
	nOutput.setInput(0, nIBK_main)


	# KILL IBKS
	#
	# deletes the entire IBKColour stack, called before creating a new stack with new inputs from the user
	def killIBKS():
		listNames = []
		allIBKs = nuke.allNodes("IBKColourV3")
		for i in allIBKs:
			n = i['name'].value()
			listNames.append(n)

		for i in listNames:
			if i != "IBK00":
				node = nuke.toNode(i)
				nuke.delete(node)
		try:
			nOutput.setInput(0, nIBK_main)    
		except ValueError:
			return



	# IBK COLOR STACK CHAIN FUNCTION
	#
	# creates the stack of IBKColour nodes
	#
	def stackChain():
		killIBKS()

		try:
			nIBK_main.knob("screen_type").setValue(k_screenType.value())
			nIBK_main.knob("Size").setValue(k_size.value())
			nIBK_main.knob("off").setValue(k_darks.value())
			nIBK_main.knob("mult").setValue(k_lights.value())
			nIBK_main.knob("erode").setValue(k_erode.value())
			nIBK_main.knob("multi").setValue(k_patchBlack.value())
		except ValueError:
			return

		
		numStacks = k_numStacks.value()
		bFirstStack = True
		bLastStack = False

		for i in range(numStacks):
			nodeName = "IBK0" + str(i + 1) 
			nIBKcolour = nuke.nodes.IBKColourV3(name = nodeName)

			nuke.toNode(nodeName).knob("screen_type").setValue(k_screenType.value())
			nuke.toNode(nodeName).knob("Size").setValue(k_size.value())
			nuke.toNode(nodeName).knob("off").setValue(k_darks.value())
			nuke.toNode(nodeName).knob("mult").setValue(k_lights.value())
			nuke.toNode(nodeName).knob("erode").setValue("0")
			nuke.toNode(nodeName).knob("multi").setValue(float(2**i))

			if bFirstStack:
				bFirstStack = False
				nIBKcolour.setInput(0, nIBK_main)
				nPrevIBK = nIBKcolour
			if (numStacks - 1) == i:
				bLastStack = True
				nIBKcolour.setInput(0, nPrevIBK)
				nOutput.setInput(0, nIBKcolour)
			else:
				nIBKcolour.setInput(0, nPrevIBK)
				nPrevIBK = nIBKcolour

		if k_expand.value() == True:
			nGroup.expand()
	
	
	# IBK CALLBACK FUNCTION
	#
	# executes the stackChain() function if a knob on this group is changed 
	def IBKCallback():
		options = ['screenType', 'size', 'darks', 'lights', 'erode', 'patchBlack', 'numStacks', 'expand']
		if nuke.thisKnob().name() in options:
			stackChain()
	
	
	nuke.addKnobChanged(IBKCallback, nodeClass="Group")
	nGroup.end()