OptionMenuParameter = {}
OptionMenuParameter_mt = { __index = OptionMenuParameter }
setmetatable(OptionMenuParameter, Control_mt)

-- Constants
OptionMenuParameter.kHeight = 30
OptionMenuParameter.kWidth = 400
OptionMenuParameter.valueOutline = ParameterList.kValueOutlineBig

function OptionMenuParameter.Create(root, parentObject, type, startValue, valueNamePairs, onChange)
	-- Create object
	local optionMenuParameter = Control.Create(root, parentObject)
	setmetatable(optionMenuParameter, OptionMenuParameter_mt)
	
	-- Create parameter value surfaces
	optionMenuParameter.valueSurface = GSurface(OptionMenuParameter.kWidth, OptionMenuParameter.kHeight)
	
	-- Set attributes
	optionMenuParameter.type = type
	optionMenuParameter.value = startValue
	optionMenuParameter.valueNamePairs = valueNamePairs
	optionMenuParameter:SetIndex(optionMenuParameter:GetIndexForValue(startValue))
	optionMenuParameter.onChange = onChange
	
	return optionMenuParameter	
end

function OptionMenuParameter:SetValue(value)
	self.value = value
	self:SetIndex(self:GetIndexForValue(self.value))
	
	if (self.onChange) then
		self.onChange(self.valueNamePairs[self.index][1])
	end
end

function OptionMenuParameter:SetIndex(index)
	self.index = index

	self:UpdateValueSurface()	
end

function OptionMenuParameter:GetIndexForValue(value)
	for i,v in ipairs(self.valueNamePairs) do
		if (v[1]==value) then
			return i
		end
	end
	
	error("Could not find value "..value.." in list. Did you choose a default value that is in the list?")
	return nil
end

function OptionMenuParameter:HandleEvent(window, rect, event)
	window:PushScissor(rect)
		local rect = window.currentScissor
		
		local isHot = rect:IsPointInside(event.pos) and not self:IsOtherControlActive()
		
		if (self.isActive==false) then
			if (event.type==kGEventMouseMoved) then
				self:SetHot(isHot)
			elseif (event.type==kGEventMouseDown) then
				if (event.button==kGEventMouseButtonLeft) then
					if (self.isHot) then
					
						-- spawn menu
						if (self.type == intruder.ZParameter_kTypeFunctionReference) then
							if (root.functionMenuChanged) then
								-- special case for function ref nodes - nested menus per page
								local menuEx = ContextMenuEx.Create()	
								local pageTables = {}
								local pageFunctions  = {} 
								local pageFunctionIndexes = {}
								local pageCounts = {}

								-- placeholders for page functions
								for i=1, root.graph.numPages do
									pageFunctions[i] = {}
									pageFunctionIndexes[i] = {}
									pageCounts[i] = 0
								end

								-- cache pages to table
								for pageIndex=1,root.graph.numPages do
									pageTables[pageIndex] = SavePageToTable(pageIndex-1)
								end
							
								-- iterate over global functions
								for i,v in ipairs(self.valueNamePairs) do
									local funcName = v[2]
									-- find page containing func
									for pageIndex=1,root.graph.numPages do
										local page = pageTables[pageIndex]
										for i,node in ipairs(page.nodes) do
											if (node.type == intruder.kNodeTypeFunction and node.name == "'" .. funcName .. "'") then 
												pageFunctions[pageIndex][pageCounts[pageIndex]+1] = funcName
												pageFunctionIndexes[pageIndex][pageCounts[pageIndex]+1] = v[1]
												pageCounts[pageIndex] = pageCounts[pageIndex]+1
											end
										end
									end
								end

								-- add no ref node
								-- NOTE: assumes no ref node to be at position 0 in root.functionList
								menuEx:AddItem(0+1000, self.valueNamePairs[1][2], function() self:SetValue(self.valueNamePairs[1][1]) end)
							
								-- create the sub menus for pages
								for pageIndex=1,root.graph.numPages do
									if (pageCounts[pageIndex] > 0) then
										local subMenuEx = ContextMenuEx.Create()	
										for i=1, pageCounts[pageIndex] do			
											subMenuEx:AddItem(pageFunctionIndexes[pageIndex][i]+1000, pageFunctions[pageIndex][i] , function() self:SetValue(pageFunctionIndexes[pageIndex][i]) end)						
										end
										menuEx:AddMenu(subMenuEx.menu, pageTables[pageIndex].name);	
									end
								end

								root.functionMenuChanged = false
								root.menuExFunctions = menuEx

							end

							-- show menu
							local result = root.menuExFunctions:SelectAt(rect:GetBottomLeft())
							if (result~=0) then							
								self:SetValue(result-1000)
							end
						else
							local menu = ContextMenu.Create()
							for i,v in ipairs(self.valueNamePairs) do
								menu:AddItem(v[2], function() self:SetValue(v[1]) end)
							end
							menu:SelectAt(rect:GetBottomLeft())
						end
						
					end
				end
			end
		end
	window:PopScissor()
end

function OptionMenuParameter:Draw(window, rect)
	window:PushScissor(rect)
		self.valueSurface:DrawTexture(rect:GetTopLeft())
		
		if (self.isHot) then
			self.valueOutline:DrawTexture(rect:GetTopLeft())
		end
	window:PopScissor()
end

function OptionMenuParameter:UpdateValueSurface(index)
	local str = self.valueNamePairs[self.index][2]
	local surface = self.valueSurface
	surface:Clear(GColor(0, 0, 0, 0))
	surface:DrawTextAligned(intruder.kFontFaceEnvyBold, str, GColor(0, 0, 0), 13, kGAlignCenter, kGVerticalAlignCenter, GPoint(1,1));
	surface:DrawTextAligned(intruder.kFontFaceEnvyBold, str, GColor(255, 255, 255), 13, kGAlignCenter, kGVerticalAlignCenter, GPoint(0,0));
	surface:UpdateTexture()
end