class 'orderTelephoneEvent' (interface)

--
-- order object types
-- all these types are suitable to be used for the order telephone event!
orderTelephoneEvent.registeredTypes =
{
	"Telephone",
}

-- configuration variables
orderTelephoneEvent.baseName = ""								-- appearance of the mailman
orderTelephoneEvent.pool = {}									-- product pool
orderTelephoneEvent.chances = {}								-- product chances
orderTelephoneEvent.timeUntilRingMin = 0						-- minimum time until the phone rings
orderTelephoneEvent.timeUntilRingMax = 0						-- maximum time until the phone rings
orderTelephoneEvent.timeUntilNextOrder = 0						-- interval at which the orders come
orderTelephoneEvent.timeUntilEnd = 0							-- time allowed to make all products
orderTelephoneEvent.timeTransfer = 400							-- time it takes to transfer the order
orderTelephoneEvent.waitX = 0									-- position the mailman waits inside
orderTelephoneEvent.waitY = 0
orderTelephoneEvent.workX = 0									-- position emily will be to deliver the order
orderTelephoneEvent.workY = 0
orderTelephoneEvent.workTelephoneOffsetX = 0					-- position emily will be to answer the phone relative to it
orderTelephoneEvent.workTelephoneOffsetY = 0					
orderTelephoneEvent.numProductsPerOrder = 0						-- number of products ordered each order
orderTelephoneEvent.numOrders = 0								-- total number of orders
orderTelephoneEvent.workAnim = "IDLE"							-- animation played by mailman
orderTelephoneEvent.workAnimEmily = "WORK_RIGHT"				-- animation played by mailman
orderTelephoneEvent.sequenceRing = nil
orderTelephoneEvent.sequenceDone = nil
orderTelephoneEvent.sequenceWin = nil
orderTelephoneEvent.sequenceLose = nil
orderTelephoneEvent.score = 0									-- score per product
orderTelephoneEvent.scoreClient = nil							-- where the score emerges from
orderTelephoneEvent.maxBalloonSize = 0

orderTelephoneEvent.telephoneBarOffsetX = 0
orderTelephoneEvent.telephoneBarOffsetY = -90

-- internal variables
-- don't change unless you know what you're doing
orderTelephoneEvent.telephone = nil
orderTelephoneEvent.mailman = nil
orderTelephoneEvent.order = nil
orderTelephoneEvent.countOrders = 0
orderTelephoneEvent.countHanded = 0
orderTelephoneEvent.timer1 = 0
orderTelephoneEvent.timer2 = 0
orderTelephoneEvent.started = false
orderTelephoneEvent.completed = false
orderTelephoneEvent.state = "wait to ring"
orderTelephoneEvent.chanceTotal = 0

function orderTelephoneEvent:__init() super()
end

function orderTelephoneEvent:onLevelInited()

	if (self.telephone ~= nil) then

		-- set enter timer
		self.timer1 = getRandomRange(self.timeUntilRingMin, self.timeUntilRingMax)

		-- create mailman
		self.mailman = pm:createPerson("mailman")
		self.mailman:setPosition(grid:getNode(entryX, entryY))		
		self.mailman:setVisible(false)

		-- create order
		self.order = createOrder()
		
		-- calculate order position
		x = -self.telephone:getAnchorX() + self.telephone:getWidth()/2
		y = -self.telephone:getAnchorY()
		
		-- place order
		self.order:setX(x)
		self.order:setY(y)
		self.order:setAnchorPointType(BOTTOMCENTER)		
		self.order:setPivotPointType(BOTTOMCENTER)
		self.order:setMoneyOrder(false)
		self.order:setMaxBalloonSize(self.maxBalloonSize)
		self.order:setVisible(false)
		self.telephone:addChild(self.order)
		
		-- calculate total chance
		self.chanceTotal = 0
		for index, value in ipairs(self.chances) do
			self.chanceTotal = self.chanceTotal + value
		end  
		
		-- initialize progress bar
		self.mailman.pb = createDefaultFillProgressBar();
		self.mailman.pb:setProgress(1)	
		self.mailman.pb:setY(-150)
		self.mailman.pb:setVisible(false)
		self.mailman:addChild(self.mailman.pb)
		
		self.telephone.pb = createDefaultFillProgressBar();
		self.telephone.pb:setProgress(1)
		self.telephone.pb:setX(self.telephoneBarOffsetX)
		self.telephone.pb:setY(self.telephoneBarOffsetY)
		self.telephone.pb:setVisible(false)
		self.telephone:addChild(self.telephone.pb)
		
		-- initialize event bar
		eventBar:setStartAmount(0)
		eventBar:setTargetAmount(self.timeUntilEnd / 1000)
		eventBar:setProgress(self.timeUntilEnd / 1000)				
		eventBar:setDescriptionText(getText("EVENTBAR"))

	else
	
		warn("orderTelephoneEvent - no order telephone found")	
	
	end

end

function orderTelephoneEvent:createObject(desc)
  
  	result = nil
  
	for index, value in ipairs(self.registeredTypes) do
		if (value == desc:getType()) then
			result = orderTelephone()
			result.event = self
			result:setType(desc:getType())
			break;
		
		end
	end  	
	
	if (result ~= nil) then
		
		if (self.telephone == nil) then
			self.telephone = result
			
		end
			
	end
  
  	return result

end

function orderTelephoneEvent:createPerson(class)

	result = nil
	
	if (class == "mailman") then
		result = orderMailman(self.baseName)
		result.scoreClient = self.scoreClient
		result.event = self		
		result:setType("mailman")
	
	end
	
	return result

end

function orderTelephoneEvent:calcProduct()

	local random = getRandomRange(0, self.chanceTotal)
	
	local counter = 0
	for index, value in ipairs(self.chances) do
		counter = counter + value
		
		if (random <= counter) then
			return self.pool[index]
			
		end
		
	end
	
	return "error"		

end

function orderTelephoneEvent:onDayBegin()

	self.started = true

end

function orderTelephoneEvent:onTick(time)

	if (self.started == false) then
		return
	end
	
	if (self.completed == true) then
		return
	end
	
	if (self.state == "wait to ring") then
	
		self.timer1 = self.timer1 - time;
		if (self.timer1 <= 0) then
			self.state = "ringing"
			
			self.telephone:playSound("SOUND_PHONE_RINGS", true)
			self.telephone:createOverhead("INGAME_EMILY_PHONE")
			emily:createOverhead("INGAME_EMILY_PHONE")
		
		end
		
	elseif (self.state == "ordering") then
	
		self.timer1 = self.timer1 - time		
		if (self.timer1 < 0) then
			self.timer1 = 0
		end
		
		local progress = self.timer2/self.timeUntilEnd
		eventBar:setProgress(self.timer2/1000)
		self.mailman.pb:setProgress(progress)
		self.telephone.pb:setProgress(progress)
		
		if (self.timer1 <= 0) then
		
			-- add a new order
			for i = 1, self.numProductsPerOrder do
				self.order:addProduct(self:calcProduct())
			end
			
			-- increase order counter
			self.countOrders = self.countOrders + 1
			
			-- pop
			if (self.countOrders == 1) then
				self.order:setVisible(true)
				self.order:popIn()
				emily:playSound("SOUND_EVENT_ATTENTION")
			
			end			
			
			-- reset timer
			self.timer1 = self.timeUntilNextOrder
	
		end
		
		-- handle end timer
		self.timer2 = self.timer2 - time

		-- handle state
		if (self.countOrders == self.numOrders) then
			self.state = "waiting until end"
			
		end
		
	elseif (self.state == "waiting until end") then

		self.timer2 = self.timer2 - time		
		if (self.timer2 < 0) then
			self.timer2 = 0
		end
		
		local progress = self.timer2/self.timeUntilEnd
		eventBar:setProgress(self.timer2/1000)
		self.mailman.pb:setProgress(progress)
		self.telephone.pb:setProgress(progress)
		
		if (self.timer2 <= 0) then

			-- event failed
			self:onDone()
		
		end
		
	else
		
		-- do nothing	
			
	end
	
end

function orderTelephoneEvent:onDayEnd()

	if (not self.completed) then
		if (self.state == "ordering" or self.state == "waiting until end") then
			autoAllPeopleWalkOut = false
			self:onDone()
			scene:qFinishGame()
		end	
	end

end

function orderTelephoneEvent:onDone()

	-- check the order
	if (self.order:isCompleted()) then
		self.state = "win"
		emily:playSound(self.soundEventCompleteAll)
	
	else
		self.state = "lose"
		
	end
	
	-- destroy it	
	self.order:setObsolete(true)
	self.order = nil
		
	-- this makes sure we can't click on the mailman anymore
	-- and hide it's progress bar
	self.mailman.pb:setVisible(false)
	self.mailman.pb = nil
	self.mailman:getHighlight():clear()    
	self.mailman:getHighlight():setActive(false)
	
	self.telephone.pb:setVisible(false)
	self.telephone.pb = nil
	self.telephone:getHighlight():clear()    
	self.telephone:getHighlight():setActive(false)

	-- done sequence
	qInsertSequence(self.sequenceDone)	

	-- state
	self.completed = true	
	
	-- eventbar
	eventBar:animateToDeactive()

end

function orderTelephoneEvent:onNotify(notification)

	if (notification == "start ordering") then
		self.state = "ordering"
		self.timer1 = 0
		self.timer2 = self.timeUntilEnd
		eventBar:animateToActive()
		
		-- only show one progress bar
		-- if the mailman is visible, show it on him
		-- otherwise on the phone
		if (self.mailman:isVisible()) then
			self.mailman.pb:setVisible(true)
		else
			self.telephone.pb:setVisible(true)
		end
	
	elseif (notification == "win lose") then
		
		if (self.state == "win") then
			qInsertSequence(self.sequenceWin)
		
		elseif (self.state == "lose") then
			qInsertSequence(self.sequenceLose)
		
		end
	
	end

end

-- an order telephone
class 'orderTelephone' (D2Object)

-- internal variables
-- don't change unless you know what you're doing
orderTelephone.event = nil
orderTelephone.order = nil

orderTelephone.pb = nil			-- Timer bar

function orderTelephone:__init() super()
end

function orderTelephone:onCreate()

	self:animate(self:getBaseName(), 0)
	self:createHighlight()
	
end

function orderTelephone:onClick()

	if (self.event.state == "ringing") then
		if (self:isSelected() == false) then
			self:setSelected(true)
			emily:qWorkOn(self)
			
		end
	end

	if (self.event.state == "ordering" or self.event.state == "waiting until end") then	
		if (self.event.mailman:isSelected() == false) then	
			emily:qWorkOn(self.event.mailman)
			self.event.mailman:setSelected(true)
	
		end
		
	end
	
end

function orderTelephone:onWorkStart(task)

	self:setSelected(false)

	if (self.event.state == "ringing") then

		-- change state
		self.event.state = "answering"		
	
		-- set task duration
		task:setDuration(0)
	
		-- clear overhead images
		self:clearOverhead()
		emily:clearOverhead()
		
		-- clear sound
		self:stopSound("SOUND_PHONE_RINGS")
	
		qInsertSequence(self.event.sequenceRing)
		
		return true
		
	end	
	
	return false

end

function orderTelephone:getWorkNode()

	  workNode = D2Object.getWorkNode(self)
	  
	  x = workNode:getGridX()
	  y = workNode:getGridY()
	  
	  x = x + self.event.workTelephoneOffsetX
	  y = y + self.event.workTelephoneOffsetY
	  
	  return grid:getNode(x, y)

end

-- an order mailman
class 'orderMailman' (npc)

orderMailman.scoreClient = nil

-- internal variables
-- don't change unless you know what you're doing
orderMailman.event = nil
orderMailman.pb = nil

function orderMailman:__init(baseName) super(baseName)
end

function orderMailman:onCreate()

	self:animate("IDLE", 0)
	self:createHighlight()
	
end

function orderMailman:onClick()
	
	if (self:isSelected() == false) then
  
		emily:qWorkOn(self)
		self:setSelected(true)
    
	end
	
end

function orderMailman:onWorkStart(task)

	self:setSelected(false)

	-- time it takes to transfer the order
	task:setDuration(self.event.timeTransfer)
	
	-- hand over products
	n = tray:distributeProducts(self.event.order)
	if (n > 0) then
		
		-- draw order
		self.event.order:draw()	

		-- animate emily
		emily:animate(self.event.workAnimEmily, 1)
	  
		-- animate mailman
		self:animate(self.event.workAnim, 1)
		
		-- update count
		self.event.countHanded = self.event.countHanded + n
  		
		-- check end
		if (self.event.state == "waiting until end") then
			if (self.event.order:isCompleted()) then
				self.event:onDone()
				
			end
		end
		
		-- score
		if (self.scoreClient == nil) then
			self.scoreClient = self
		end
		
		incScore(self.event.score * n, self.scoreClient:getScreenX(), self.scoreClient:getScreenY() + scorePersonFloaterOffsetY)
		emily:playSound(self.event.soundEventCompleteOne)
		
	end
	
	return true
	
end

function orderMailman:onWorkComplete(task)

	self:animate("IDLE", 0)
	emily:animate("IDLE", 0)

end

function orderMailman:getWorkNode()
  
	return grid:getNode(self.event.workX, self.event.workY)
  
end