-- global skater variables
skaterId = 0
skaters = {}
skaterCount = 0
skaterCountMax = 2
skaterCountBusy = 0
skaterSoundPlaying = false
skaterInjure = 0
skaterInjureScore = 50
skaterSuckItUpTimeMin = 15000
skaterSuckItUpTimeMax = 15001
skaterSkateTimeMin = 10.75 * 60 * 1000 
skaterSkateTimeMax = 11.50 * 60 * 1000

-- global skater area variables
skaterAreaEnterX = 5
skaterAreaEnterY = 26
skaterAreaLeaveX = 4
skaterAreaLeaveY = 26
skaterAreas =
{
	{0, 16, 9, 22},
	{0, 23, 7, 24},
	{0, 25, 4, 27},
	{3, 28, 8, 32},
}

-- state variables
kStateDead = "dead"
kStateWalkingIn = "walking in"
kStateWalkingOut = "walking out"
kStateSkating = "skating"
kStateFalling = "falling"
kStateInjured = "injured"
kStateOutside = "outside"

-- skater
class 'skater' (fakecustomer)
skater.id = -1
skater.state = kStateDead
skater.walkTimePerNode = -1
skater.order = nil
skater.timerSuckItUp = 0
skater.timerSkate = 0
skater.outsideTimer = 0
skater.originalAnchorBotY = 0
skater.healing = false

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

function skater:onCreate()

	fakecustomer.onCreate(self)
	self:register()
	
	self.originalAnchorBotY = self:getAnchorBotY()
	
end

function skater:onPlace()

	fakecustomer.onPlace(self)
	self:doWalkingIn()

end

function skater:register()
	
	skaterId = skaterId + 1
	self.id = skaterId
	skaters[self.id] = self
	skaterCount = skaterCount + 1

end

function skater:unregister()

	skaters[self.id] = nil
	skaterCount = skaterCount - 1

end

function skater:onTick(time)

	fakecustomer.onTick(self, time)

	if (dayEnded) then
		return
	end
	
	if (scene:isPlayingMovie()) then
		return
	end
	
	if (scene:isStartingMovie()) then
		return
	end	

	if (self.state == kStateWalkingIn) then
	
	elseif (self.state == kStateWalkingOut) then
	
	elseif (self.state == kStateSkating or self.state == kStateOutside) then
		if (self.timerSkate > 0) then
			self.timerSkate = self.timerSkate - time
			if (self.timerSkate <= 0) then
				-- see skater:onSkated
			end			
		end
	elseif (self.state == kStateFalling) then
	
	elseif (self.state == kStateInjured) then
		if (not self.healing) then
			if (self.timerSuckItUp > 0) then
				self.timerSuckItUp = self.timerSuckItUp - time
				if (self.timerSuckItUp <= 0) then
					self:orderClear()
					self:doSkating()
				end
			else
				assert(nil)
			end
		end
	elseif (self.state == kStateDead) then
	
	else
		assert(nil)	
	end

end

function skater:doWalkingIn()
	self.state = kStateWalkingIn
	self.walkTimePerNode = self:getWalkTimePerNode()
	self.timerSkate = getRandomRange(skaterSkateTimeMin, skaterSkateTimeMax)
	self:orderClear()	
	self:qWalkToXY(32, skaterAreaEnterY)
	self:qWalkToXY(skaterAreaEnterX, skaterAreaEnterY)
	self:qWalkToXY(skaterAreaLeaveX, skaterAreaLeaveY)
	self:qCallback(self, self.onWalkedIn)
end

function skater:doWalkingOut()
	self.state = kStateWalkingOut
	self:orderClear()
	self:qWalkToXY(skaterAreaLeaveX, skaterAreaLeaveY)
	self:qSetAppearance("")
	self:qCallback(self, function()
		self:setShadowVisible(true)
		self:setAnchorBotY(self.originalAnchorBotY)
	end)
	self:qWalkToXY(skaterAreaEnterX, skaterAreaEnterY)
	self:qSetWalkTimePerNode(self.walkTimePerNode)
	self:qWalkToXY(exitX, exitY)
	self:qCallback(self, self.onWalkedOut)
end

function skater:doDead()
	self.state = kStateDead
	self:orderClear()
	self:unregister()
	self:setVisible(false)
	self:qDestroy()
end

function skater:doSkating()
	self.state = kStateSkating
	self:orderClear()
	self:setAppearance("SKATE")
	self:removeHighlight()

	self:setShadowVisible(false)
	self:setAnchorBotY(self.originalAnchorBotY + 30)

	self:setWalkTimePerNode(self.walkTimePerNode * 2)
	self:setOverheadY(0)
	local startedSkating = false
	while (not startedSkating) do
		local goingOutside = getRandom(3) -- 30% change going outer lake
		if (goingOutside == 1) then
			local exitX = 0
			local exitY = getRandom(GRID_SIZE_Y)
			local enterX = getRandom(GRID_SIZE_X) + 2 --should have horizontal facing to create realistic come back from outer lake
			local enterY = getRandom(GRID_SIZE_Y)
			
			for i, area in ipairs(skaterAreas) do
				if (self:contains(area, exitX, exitY) and self:contains(area, enterX, enterY)) then
					if (self:distance(self:getPosition():getGridX(), self:getPosition():getGridY(), exitX, exitY) >= 5) then
						if (not grid:getNode(exitX, exitY):isBlocked() and not grid:getNode(enterX, enterY):isBlocked()) then
							cout("status: skater went outside - starting sequence\n")
							self:qWalkToXY(exitX, exitY)
							self:qSetVisible(false)
							self:qCallback(self, self.decSkaterCount)
							self:qWait(getRandomRange(2000, 5000))
							self:qWalkToXY(0, enterY)
							self:qSetVisible(true)
							self:qCallback(self, self.incSkaterCount)
							self:qWalkToXY(enterX, enterY)
							self:qCallback(self, self.onSkated)
							startedSkating = true
							break
						end
					end
				end
			end
		else
			local targetX = getRandom(GRID_SIZE_X)
			targetX = targetX + 1 --else skaters will get too close to the edge, 0 is included in area for outsideskating
			local targetY = getRandom(GRID_SIZE_Y)
			for i, area in ipairs(skaterAreas) do
				if (self:contains(area, targetX, targetY)) then
					if (self:distance(self:getPosition():getGridX(), self:getPosition():getGridY(), targetX, targetY) >= 5) then
						if (not grid:getNode(targetX, targetY):isBlocked()) then
							self:qWalkToXY(targetX, targetY)
							self:qCallback(self, self.onSkated)
							startedSkating = true
							break
						end
					end
				end
			end
		end	
	end
	
	if (startedSkating) then
		self:incSkaterCount()
	end
end

function skater:doFall()
	self.state = kStateFalling
	self:orderClear()
	self:qAnimateWait("FALL", 1, false, -1, true)
	self:qWait(500)
	self:qCallback(self, self.onFell)
end

function skater:doInjury()
	self.state = kStateInjured
	self.timerSuckItUp = getRandomRange(skaterSuckItUpTimeMin, skaterSuckItUpTimeMax) * um:getMiscMultiplier()
	self:orderClear()
	self:setOverheadY(40)
	self:createHighlight()
	self:orderBandage()
	self:qAnimate("WAVE", -1, 8)
end

function skater:onWalkedIn()
	self:doSkating()
end

function skater:onWalkedOut()
	self:doDead()
end

function skater:onSkated()
	self:decSkaterCount()

	if (scene:isClosed()) then
		self:doWalkingOut()
	elseif (self.timerSkate > 0) then
		
		if (skaterInjure == 0) then
			self:doSkating()
		else
			skaterInjure = skaterInjure - 1
			self:doFall()
		end

	else
		self:doWalkingOut()
	end
end

function skater:onFell()
	self:doInjury()
end

function skater:onClick()
	self:clearOverhead()
	if (not self:isSelected()) then
		self.healing = true
		self:setSelected(true)
		self:animate("IDLE", 0)
		emily:qWorkOn(self)	
	end
end

function skater:onWorkStart(task)
	self:setSelected(false)
	if (self.state == kStateInjured) then
		local n = tray:distributeProducts(self.order)
		if (n > 0) then
			self:orderClear()
			task:setDuration(2000)
			task:getPerson():animate("FIX", -1)
			self:playSound("SOUND_APPLY_1STAID", true)
			return true
		end
	end
	self.healing = false
	return false
end

function skater:onWorkUpdate(task, time)
	return false
end

function skater:onWorkComplete(task)
	incScore(skaterInjureScore, task:getPerson():getScreenX(), task:getPerson():getScreenY() + scorePersonFloaterOffsetY)
	self:qWait(500)
	self:qCallback(self, self.doSkating)
	self:stopSound("SOUND_APPLY_1STAID")
	self:playSound("SOUND_EVENT_COMPLETE_ITEM")
	self.healing = false
end

function skater:distance(sx, sy, dx, dy)
	local x = dx - sx
	local y = dy - sy
	return math.sqrt(x*x + y*y)
end

function skater:contains(rectangle, x, y)
	assert(#rectangle == 4)
	local left = rectangle[1]
	local top = rectangle[2]
	local right = rectangle[3]
	local bottom = rectangle[4]
	local width = right - left
	local height = bottom - top
	
	local x_ = x - left
	local y_ = y - top
	
	if (x_ < 0) then
		return false
	end
	
	if (y_ < 0) then
		return false
	end
	
	if (x_ >= width) then
		return false
	end
	
	if (y_ >= height) then
		return false
	end
	
	return true

end

function skater:orderBandage()
	assert(not self.order)
	self.order = createOrder()
	x = -self:getAnchorX() + self:getWidth() / 2
	y = -self:getAnchorY() + 60
	self.order:setX(x)
	self.order:setY(y)
	self.order:setAnchorPointType(BOTTOMCENTER)		
	self:addChild(self.order)
	self.order:addProduct("BANDAGE")
	self.order:popIn()	
end

function skater:orderClear()
	if (self.order) then
		self.order:qPopOut()
		self.order:qDestroy()		
		self.order = nil
	end
end

function skater:incSkaterCount()
	skaterCountBusy = skaterCountBusy + 1
end

function skater:decSkaterCount()
	skaterCountBusy = skaterCountBusy - 1
end