class 'npcChaseEvent' (interface)

npcChaseEvent.timeUntilEnterMin = 0
npcChaseEvent.timeUntilEnterMax = 0

npcChaseEvent.timerReturn = 2000

npcChaseEvent.started = false
npcChaseEvent.completed = false

npcChaseEvent.scoreGotOne	= 0
npcChaseEvent.scoreGotAll	= 0
npcChaseEvent.actionDuration = 1000
npcChaseEvent.caughtSounds = {}
npcChaseEvent.overheadY = 8

-- Various sequences
npcChaseEvent.sequenceStart = nil
npcChaseEvent.sequenceLose = nil
npcChaseEvent.sequenceWin = nil

npcChaseEvent.sequenceDayEnd = nil

-- The NPCs involved in the chase
npcChaseEvent.characters = {}

-- internal
npcChaseEvent.timer = 0
npcChaseEvent.timerInited = false
npcChaseEvent.nrCharacters = 0

--
function npcChaseEvent:__init() super()
end

--
function npcChaseEvent:onLevelInited()

	self.timer = getRandomRange(self.timeUntilEnterMin, self.timeUntilEnterMax)
	self.timerInited = true
	
	for index, value in ipairs(self.characters) do
		value:createHighlight()
		value:setClickable(false)
		value:setOverheadY(self.overheadY)
	end
	
end

function npcChaseEvent:onTick(time)

	if (scene:isStartingMovie() or scene:isPlayingMovie()) then
		return
	end
	
	if (self.timerInited == true and self.started == false) then
		-- wait until we can enter
		if (self.timer > 0) then
			self.timer = self.timer - time
			
			if (self.timer <= 0) then
				self:onStart()
			end
			
		end
	end
	
end

function npcChaseEvent:updateProgress()

	if (self.started == true and self.completed == false) then
		-- update the progress bar
		local progress = 0
		for index, value in ipairs(self.characters) do
			progress = progress + value:getProgress()
		end
		
		eventBar:setProgress(progress)
	end
end

function npcChaseEvent:onStart()

	if (self.started == false) then
		self.started = true
		
		-- Add all the characters to the entry node
		--[[
		for index, value in ipairs(characters) do
			value:setPosition(entryNode)
			value:setStarted(true)
		end
		--]] 
		
		if (self.sequenceStart ~= nil) then
			qSequence(self.sequenceStart)
		end
	end
	
end

function npcChaseEvent:onCompleted()
	
	if (self.completed == false) then
		self.completed = true
		
		emily:playSound(self.soundEventCompleteAll)
		incScore(self.scoreGotAll, emily:getScreenX(), emily:getScreenY() + scorePersonFloaterOffsetY, scoreBonusFloaterDelay, "BONUS")
		
		if (self.sequenceWin ~= nil) then
			qSequence(self.sequenceWin)
		end
		
		-- update the eventbar
		eventBar:animateToDeactive()
	end
	
end

function npcChaseEvent:onDayEnd()

	if (self.completed == false) then
		if (self.sequenceLose ~= nil) then
			qSequence(self.sequenceLose)
		end
	end
	
	if (self.sequenceDayEnd ~= nil) then
		qSequence(self.sequenceDayEnd)
	end
	
end

function npcChaseEvent:onNotify(message)
	
	if (message == "caught") then
	
		local numCaughtSounds = table.getn(self.caughtSounds)
		if (numCaughtSounds > 0) then
			emily:playSound(self.caughtSounds[getRandom(numCaughtSounds) + 1])
			
		end	
	
		if (self:isChaseOver()) then
			self:onCompleted()
		end
		
	elseif (message == "chase start") then
		local totalAmount = 0
		for index, value in ipairs(self.characters) do
			value:onStartChase()
			totalAmount = totalAmount + value:getNumberOfStoppingPoints()
		end
		
		eventBar:setStartAmount(0)
		eventBar:setTargetAmount(totalAmount)
		eventBar:setProgress(0)	
		eventBar:setDescriptionText(getText("EVENTBAR"))
		eventBar:setSubjectImage("EVENT_CHASE_BAR", player:getCurrentResourceSection())
		eventBar:animateToActive()	
		eventBar:raiseCurtain()
		
	else
		i, j = string.find(message, "arrived_")
		if (j ~= nil and j > 1) then
			npcIndexString = string.sub(message, j+1, string.len(message))
			npcIndex = tonumber(npcIndexString)
			-- cout("============== npc index " .. npcIndexString .. " arrived ================\n")
			if (npcIndex > 0 and npcIndex <= self.nrCharacters) then
				self.characters[npcIndex]:onArrived()
			end
		end
	end
	
end

function npcChaseEvent:isChaseOver()
	
	if (self.completed == false) then
	
		for index, value in ipairs(self.characters) do
			if (value.completed == false) then
				return false
			end
		end
		
	end

	return true
	
end

function npcChaseEvent:addChaseNpc(chaseNpc)
	
	-- assuming the npc is valid, otherwise luabind should nag
	self.nrCharacters = self.nrCharacters + 1
	chaseNpc.event = self
	chaseNpc.index = self.nrCharacters
	chaseNpc:setStarted(self.started)
	self.characters[self.nrCharacters] = chaseNpc
	
end

-- ============================================================================
class 'chaseNpc' (npc)

chaseNpc.coordinates = ""

-- internal
chaseNpc.coordIndex = 0
chaseNpc.coordHeighest = 0
chaseNpc.timer = 0
chaseNpc.completed = false
chaseNpc.event = nil
chaseNpc.sequenceCaught = nil
chaseNpc.arrivalAnim = nil
chaseNpc.moving = false
chaseNpc.index = 0
chaseNpc.extraChild = nil
chaseNpc.tooLate = false
chaseNpc.sequenceTooLate = nil
chaseNpc.workAnim = nil
chaseNpc.visibleWhenCaught = true
chaseNpc.first = true
chaseNpc.busy = false

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

function chaseNpc:onClick()

	if (self.moving == true or self.completed == true) then
		return
		
	end
	
	if (not self.busy) then
		self.busy = true
		self.timer = 0
		self:setSelected(true)
		self:clearOverhead()
		emily:qWorkOn(self)
		
	end
	
end

function chaseNpc:onWorkStart(task)
	
	if (self.completed) then
		self.busy = false
	    return false
	    
	end
	
    self:setSelected(false)
	
	if (self.coordinates[self.coordIndex] ~= nil) then
		if (self.workAnim ~= nil) then
			self:animate(self.workAnim, -1)
		end
		
		self:setVisible(self.visibleWhenCaught)
		
		local anim = self.coordinates[self.coordIndex][5]
		if (anim ~= nil) then
			emily:animate(anim, -1)
		end
		
		task:setDuration(self.event.actionDuration)	
			
		return true	
	end
	
	self.busy = false
	return false

end

function chaseNpc:onWorkComplete(task)

	if (self.coordIndex > self.coordHeighest) then
		incScore(self.event.scoreGotOne, emily:getScreenX(), emily:getScreenY() + scorePersonFloaterOffsetY)	
		self.coordHeighest = self.coordHeighest + 1
	end
	
	self:goToNext()
	self.busy = false
	if (not self.completed) then
		self:setVisible(true)
	else
		self:setVisible(self.visibleWhenCaught)
	end
	
	scene:qNotify("caught")	
end

function chaseNpc:addExtraChild(child)
	if (self.extraChild ~= nil) then
		self.extraChild:setObsolete(true)
		self.extraChild = nil
	end
	
	self.extraChild = child
	self:addChild(self.extraChild)
	
end

function chaseNpc:removeExtraChild()
	if (self.extraChild ~= nil) then
		self.extraChild:setVisible(false)
		self.extraChild:setObsolete(true)
		self.extraChild = nil
	end
	
end

function chaseNpc:getWorkNode()

	if (self.coordinates[self.coordIndex] ~= nil) then
		local gridx = self.coordinates[self.coordIndex][3]
		local gridy = self.coordinates[self.coordIndex][4]
		return grid:getNode(gridx, gridy)
	
	end
	
	return D2Person.getWorkNode(self)

end

function chaseNpc:onArrived()
	-- cout("Arrived")
	if (self.first) then
		self:createOverhead("INGAME_ARROW")
		self.first = false
	end
	
	self.moving = false
	self:setClickable(true)
	self.timer = self.event.timerReturn
	if (self.arrivalAnim ~= nil) then
		self:animate(self.arrivalAnim, -1)
	end
end

function chaseNpc:onTick(time)

	if (scene:isStartingMovie() or scene:isPlayingMovie()) then
		return
	end
	if (self.started == true and self.moving == false) then
		-- cout("   npc #" .. self.index .. " onTick\n")
		-- wait until we can enter
		if (self.timer > 0) then
			self.timer = self.timer - time
			
			if (self.timer <= 0) then
				self:goToPrev()
			end
			
		end
	end
	
end

function chaseNpc:onStartChase()
	self:setStarted(true)
	self:goToNext()
end

function chaseNpc:setStarted(startedFlag)
	self.started = startedFlag
end

function chaseNpc:getNumberOfStoppingPoints()
	return table.getn(self.coordinates)
end

function chaseNpc:goToNext()
	
	-- walk to next node
	-- or complete the event
	self.timer = 0
	self.coordIndex = self.coordIndex + 1
	if (self.coordinates[self.coordIndex] == nil) then
		
		if (self.sequenceCaught ~= nil) then
			qInsertSequence(self.sequenceCaught)
		end
		self.completed = true
		self:setClickable(false)
		self:removeHighlight()
			
	else
		local gridx = self.coordinates[self.coordIndex][1]
		local gridy = self.coordinates[self.coordIndex][2]
		
		self.moving = true
		self:setClickable(false)
		self:qWalkToXY(gridx, gridy)
		self:qNotify("arrived_" .. self.index)
	
	end
	
	-- update the eventbar
	self.event:updateProgress()
	
end


function chaseNpc:goToPrev()
	-- walk to previous node
	-- if available
	self.timer = 0
	if (self.coordIndex > 1) then
		self.coordIndex = self.coordIndex - 1
		
		-- too late sequence
		if (self.tooLate == false) then
			self.tooLate = true
			if (self.sequenceTooLate ~= nil) then
				qSequence(self.sequenceTooLate)
			end				
		end
		
		self.moving = true
		-- walk to previous node
		local gridx = self.coordinates[self.coordIndex][1]
		local gridy = self.coordinates[self.coordIndex][2]		
	
		self:playSound(self.event.soundEventBad)
		self:setClickable(false)
		self:qWalkToXY(gridx, gridy)
		self:qNotify("arrived_"  .. self.index)	
	end	
	
	-- update the eventbar
	self.event:updateProgress()
end

function chaseNpc:getProgress()

	if (self.coordIndex > 0) then
		return (self.coordIndex - 1)
	end
	
	return 0
	
end