-- increases score and optionally pops a floater
function incScore(score, x, y, delay, preText, postText)
 
 	if (score == 0) then
 		return
 	end
 
	addScore(score)
	
	if (x ~= nil and y ~= nil) then
	
		if (delay == nil) then
			delay = 0
		end
		
		if (preText == nil) then
			preText = ""
		else
			preText = getText(preText)
		end
		
		if (postText == nil) then
			postText = ""
		else
			preText = getText(preText)		
		end
	
		local text = string.format("%s%d%s", preText, score, postText)		
		createFloater(text, x, y, delay)
		--createFloater(preText .. score .. postText, x, y, delay)
	
	end

end

-- increases score and optionally pops a floater
function incScoreAndTip(score, tip, x, y, delay, preText, postText)
 
 	if (score == 0) then
 		return
 	end
 
	addScoreIncTip(score, tip)
	
	if (x ~= nil and y ~= nil) then
	
		if (delay == nil) then
			delay = 0
		end
		
		if (preText == nil) then
			preText = ""
		else
			preText = getText(preText)
		end
		
		if (postText == nil) then
			postText = ""
		else
			preText = getText(preText)		
		end
	
		score = score + tip
		
		local text = string.format("%s%d%s", preText, score, postText)		
		createFloater(text, x, y, delay)
		--createFloater(preText .. score .. postText, x, y, delay)
	
	end

end


-- hacky helper function to destroy the bubble
-- use with extreme care
function destroyBubble()

	local bubble = level:getBubble()
	if (bubble) then
		bubble:clear()
		bubble:destroy()
		level:setBubble(nil)
	
	end

end

function createDummyObject(type, gridX, gridY)
	local desc = D2ObjectDesc()
	desc:setType(type)
	desc:setFilename("dummy.d2p")
	desc:setGridX(gridX)
	desc:setGridY(gridY)
	om:addObject(desc)	
end

function getRandomCustomerName()
	
	local r = getRandomRange(0, 14)
	if (r == 0) then
		return "INGAME_CUSTOMER_FEMALE_REGULAR"
	elseif (r == 1) then
		return "INGAME_CUSTOMER_MALE_REGULAR"
	elseif (r == 2) then
		return "INGAME_CUSTOMER_FEMALE_DESIGNER"
	elseif (r == 3) then
		return "INGAME_CUSTOMER_MALE_DESIGNER"
	elseif (r == 4) then
		return "INGAME_CUSTOMER_FEMALE_YUPPIES"
	elseif (r == 5) then
		return "INGAME_CUSTOMER_MALE_YUPPIES"
	elseif (r == 6) then
		return "INGAME_CUSTOMER_FEMALE_BIGGIES"
	elseif (r == 7) then
		return "INGAME_CUSTOMER_MALE_BIGGIES"
	elseif (r == 8) then
		return "INGAME_CUSTOMER_FEMALE_CHILD"
	elseif (r == 9) then
		return "INGAME_CUSTOMER_MALE_CHILD"
	elseif (r == 10) then
		return "INGAME_CUSTOMER_FEMALE_ELDERLY"
	elseif (r == 11) then
		return "INGAME_CUSTOMER_MALE_ELDERLY"
	elseif (r == 12) then
		return "INGAME_CUSTOMER_MALE_FARMER"
	else
		return "INGAME_CUSTOMER_FEMALE_FARMER"
	end
	
	cout("Wrong id: getRandomCustomerName")
	return ""
end

function getSpecialRandomCustomerName()
	
	local r = getRandomRange(0, 12)
	if (r == 0) then
		return "INGAME_CUSTOMER_FEMALE_REGULAR"
	elseif (r == 1) then
		return "INGAME_CUSTOMER_MALE_REGULAR"
	elseif (r == 2) then
		return "INGAME_CUSTOMER_FEMALE_DESIGNER"
	elseif (r == 3) then
		return "INGAME_CUSTOMER_MALE_DESIGNER"
	elseif (r == 4) then
		return "INGAME_CUSTOMER_FEMALE_YUPPIES"
	elseif (r == 5) then
		return "INGAME_CUSTOMER_MALE_YUPPIES"
	elseif (r == 6) then
		return "INGAME_CUSTOMER_FEMALE_BIGGIES"
	elseif (r == 7) then
		return "INGAME_CUSTOMER_MALE_BIGGIES"
	elseif (r == 8) then
		return "INGAME_CUSTOMER_FEMALE_ELDERLY"
	elseif (r == 9) then
		return "INGAME_CUSTOMER_MALE_ELDERLY"
	elseif (r == 10) then
		return "INGAME_CUSTOMER_MALE_FARMER"
	else
		return "INGAME_CUSTOMER_FEMALE_FARMER"
	end
	
	cout("Wrong id: getRandomCustomerName")
	return ""
end

-- queue a sequence at the front
-- see below for more comments
function qInsertSequence(sequence)

	insert()
	qSequence(sequence)
	append()

end

-- queue a sequence
-- takes a table of the form:
-- {
--   { A, B, ... }
-- }
--
-- where: A is a string of the actor doing something
--        B is the function to execute
--	      ... variable number of arguments to pass to the function
function qSequence(sequence)

	if (sequence == nil) then
		warn("qSequence - sequence is nil!")
		return
			
	end

	for index, value in ipairs(sequence) do
	
		local a = expand(value[1])
		local b = value[2]
		
		local c = value[3]
		local d = value[4]
		local e = value[5]
		local f = value[6]
		local g = value[7]
		local h = value[8]
		local i = value[9]
		
		if (value[1] ~= "") then
			if (a == nil) then
				warn("qSequence error: " .. value[1] .. " is nil")
				return
			end
		end

		if (b ~= "qDestroy") then
			c_ = expand(c)
			if (c_ ~= nil) then c = c_ end		
			
			d_ = expand(d)
			if (d_ ~= nil) then d = d_ end
	
			e_ = expand(e)
			if (e_ ~= nil) then e = e_ end
			
			f_ = expand(c)
			if (f_ ~= nil) then f = f_ end		
		
			g_ = expand(g)
			if (g_ ~= nil) then g = g_ end				
			
			h_ = expand(h)
			if (h_ ~= nil) then h = h_ end					

		end
		
		if (a ~= nil) then
			if (type(a[b]) ~= "function") then
				warn("qSequence - not a function: " .. value[1] .. ":" .. b)
				return
			end		
		else
			if (type(_G[b]) ~= "function") then
				warn("qSequence - not a global function: " .. b)
				return
			end		
		end

		if (c == nil) then
			if (a ~= nil) then
				a[b](a)
			else
				_G[b]()
			end
		
		elseif (d == nil) then
			if (a ~= nil) then
				a[b](a, c)
			else
				_G[b](c)
			end
		
		elseif (e == nil) then
			if (a ~= nil) then
				a[b](a, c, d)
			else
				_G[b](c, d)
			end
		
		elseif (f == nil) then
			if (a ~= nil) then
				a[b](a, c, d, e)
			else
				_G[b](c, d, e)
			end
		
		elseif (g == nil) then
			if (a ~= nil) then
				a[b](a, c, d, e, f)
			else
				_G[b](c, d, e, f)
			end
		
		elseif (h == nil) then
			if (a ~= nil) then
				a[b](a, c, d, e, f, g)
			else
				_G[b](c, d, e, f, g)
			end		
			
		elseif (i == nil) then
			if (a ~= nil) then
				a[b](a, c, d, e, f, g, h)
			else
				_G[b](c, d, e, f, g, h)
			end				
		
		else
			warn("qSequence - too many arguments to function, maximum is 6")
	
		end
	
	end

end

-- expand function
-- to simulate php style variable variables (see php manual)
function expand(s)

	if (s == nil) then
		return nil
	end
	
	if (type(s) ~= "string") then
		return s
	end
	
	if (s == "") then
		return nil
	end
	
	if (event ~= nil) then
		if (event[s] ~= nil) then
			return event[s]
		end	
	end
	
	if (day ~= nil) then
		if (day[s] ~= nil) then
			return day[s]
		end
	end
	
	if (_G[s] ~= nil) then
		return _G[s]
	end
	
	return nil
end

--
function createDefaultFillProgressBar()

	if (makeProgressBarsSmall) then
		return createDefaultFillProgressBarSmall()
		
	else
		return createDefaultFillProgressBarLarge()
	
	end

end

--
function createDefaultFillProgressBarLarge()

	local pb = createFillProgressBar()
	pb:setBackImage("FILL_BAR", "scenegame")
	pb:setFillImage("FILL_BAR_FILLING", "scenegame")
	pb:getFill():setY(-2)
	return pb

end

--
function createDefaultFillProgressBarSmall()

	local pb = createFillProgressBar()
	pb:setBackImage("FILL_BAR_SMALL", "scenegame")
	pb:setFillImage("FILL_BAR_FILLING_SMALL", "scenegame")
	pb:getFill():setY(-2)
	return pb

end

--
function createDefaultKaraokeProgressBar()

	local pb = createFillProgressBar()
	pb:setBackImage("FIREWORKS_FILL_BAR", "restaurant_4")
	pb:setFillImage("FIREWORKS_FILL_BAR_FILLING", "restaurant_4")
	pb:getFill():setX(3)
	pb:getFill():setY(15)
	pb:setOrientation(1)
	return pb

end


--
function createDefaultCursorProgressBar()

	local pb = createCursorProgressBar()
	pb:setBackImage("HUD_BAR", "scenegame")
	pb:setCursorImage("CURSOR", "default")
	return pb

end

--
function createHeimlichBar()

	local pb = createCounterCursorProgressBar()
	pb.back = "COUNTERCURSOR_BAR"
	pb.yes = "COUNTERCURSOR_BAR_YES"
	pb.no = "COUNTERCURSOR_BAR_NO"
	pb.section = "scenegame"
	pb:setBackImage(pb.back, pb.section)
	pb:setMin(-56)
	pb:setMax(30)
	pb:setCounterImage("COUNTERCURSOR_BAR_COUNTER", pb.section)
	pb:getCounter():setX(49)
	pb:getCounter():setY(-1)
	pb:getCounter():setCurrentFrame(pb:getCounter():getFrameCount()-1)
	pb:setCursorImage("COUNTERCURSOR_BAR_CURSOR", pb.section)
	pb:getCursor():setY(-2)
	return pb


end

function table.copy(t)  
	local u = { }  
	for k, v in pairs(t) do 
		u[k] = v 
	end  
	return setmetatable(u, getmetatable(t))
end

function math.lerp(val1, val2, fact)  
	return val1 + fact * (val2 - val1)
end


List = {}
function List.new()
	return {first = 1, last = 0}
end

function List.push_back(list, value)
	list[#list+1] = value
	return value
end