-- ************************************ Special Event Room3 (Ball throw) ************************************ --
SpecialRoom3 = deriveLuaClass("SpecialRoom3", "Event")

SpecialRoom3.connor = {}
SpecialRoom3.connor.character = {}
SpecialRoom3.connor.targetx = 0
SpecialRoom3.connor.targety = 0
SpecialRoom3.ballsThrown = 0
SpecialRoom3.maxTasks = 0
SpecialRoom3.tasks = 0
SpecialRoom3.balls = {}
SpecialRoom3.timer = 0
SpecialRoom3.waving = false
SpecialRoom3.timeBetweenWaves = 1000
SpecialRoom3.timeWaving = 5
SpecialRoom3.hitsForWin = 5
SpecialRoom3.hits = 0
SpecialRoom3.scoreOneDone = 5
SpecialRoom3.scoreAllDone = 20
SpecialRoom3.completed = false
SpecialRoom3.pickingUpDroolers = false
SpecialRoom3.started = false
STATE_STILL = "still"
STATE_RUNNING = "running"


function SpecialRoom3:init(desc)
	SpecialRoom3.superInit(desc)
	self.seenArrow = false
	self.eventBarImage = desc.eventBarImage
end

SpecialRoom3.wavePositions = {
	{x=-50, y=200},
	{x=858, y=178},
}

SpecialRoom3.kidPositions = {
	{x=150, y=200},
	{x=750, y=188},
}

function SpecialRoom3:onInitialized()
	self.connor.character = resident
	SpecialRoom3.super.onInitialized(self)
	self.firstTime = true

	eventBar.startValue = 0
	eventBar.targetValue = self.maxTasks
	eventBar.progress = 0
	eventBar.description = ""
	eventBar.icon = self.eventBarImage
end

function SpecialRoom3:onShiftStart()
	--hintManager:handle({id="ball_event", sprite=self.connor.character})
end

function SpecialRoom3:createPostShiftAnimation()
end

function SpecialRoom3:onTick(time)
	if (self.started and self.completed == false and self.waving == false and not self.pickingUpDroolers) then
		self.timer = self.timer - time
		if (self.timer < 0) then
			taskSystem:cancelAllTasksFor(self.connor.character)
			self.pickingUpDroolers = true
			level:resetDroolingPatients()
			level:handleDroolingPatients()
			self.connor.character:addTask({class="CallTask", func=function() self.pickingUpDroolers = false end})
			self.connor.character:addTask({class="CallTask", func=function() self.waving = true end})
			self.connor.character:addTask({class="CallTask", func=function() self:addBallTask() end})
		end
	end
end

function SpecialRoom3:addWalkToTask()
		local pos,x,y = 0,0,0
		repeat
			pos = math.Random(1,table.icount(self.wavePositions))
			x = self.wavePositions[pos].x
			y = self.wavePositions[pos].y
		until(self.connor.targetx ~= x and self:getDist(hero.x,x,hero.y,y) > 20)

		self.connor.targetx = x
		self.connor.targety	= y
		self.connor.character:addTask({class="SetTask", baseAnimation="CONNOR_RUN"})
		self.connor.character:addTask({class="SetTask", state=STATE_RUNNING})
		self.connor.character:addTask({class="WalkToTask", target={x=x,y=y}})
		self.connor.character:addTask({class="SetTask", baseAnimation="CONNOR"})
		self.connor.character:addTask({class="CallTask", func=SpecialRoom3.addWalkToTask, object=self, actor=self.connor.character})
				
		self.connor.character:addTask({class="WalkToTask", target={x=x,y=y}})
		self.connor.character:addTask({class="SetTask", baseAnimation="CONNOR"})
		self.connor.character:addTask({class="CallTask", func=SpecialRoom3.addWalkToTask, object=self, actor=self.connor.character})
				
		for i=1, 2 do
			self.extraCharacters[i]:addTask({class="Task", duration=(i*200)+100})
			self.extraCharacters[i]:addTask({class="WalkToTask", target={x=self.kidPositions[pos].x - (i-1)*20, y=self.kidPositions[pos].y - (i-1)*20}})
		end
end

function SpecialRoom3:addBallTask()
	if (self.tasks < self.maxTasks) then
		self.tasks = self.tasks + 1
		local pos,x,y = 0,0,0
		repeat
			pos = math.Random(1,table.icount(self.wavePositions))
			x = self.wavePositions[pos].x
			y = self.wavePositions[pos].y
		until(self.connor.targetx ~= x and self:getDist(hero.x,x,hero.y,y) > 200)

		self.connor.targetx = x
		self.connor.targety	= y
		self.connor.character:addTask({class="WalkToTask", target={x=178, y=300}})
		self.connor.character:addTask({class="SetTask", state=STATE_STILL, baseAnimation="CONNOR"})
		if (self.firstTime) then
			self.firstTime = false
			self.connor.character:addTask({class="MessageTask", duration=1000, textId="TEXT_R3_SH3_7"})		
		end
		self.connor.character:addTask({class="SetTask", clickable=true})
		self.connor.character:addTask({class="CallTask", func=function() hintManager:handle({id="ball_event", sprite=self.connor.character}) end})
		self.connor.character:addTask({class="PlayAnimationTask", animation="WAVE_ARMS#LEFT", cycles=self.timeWaving, frameTime=100, wait=true})
		self.connor.character:addTask({class="SetTask", clickable=false})
		self.connor.character:addTask({class="CallTask", func=SpecialRoom3.stopWaving, object=self, actor=self.connor.character})
	else
		--done
		self.waving = false
		self.pickingUpDroolers = false
		self.completed = true
		self.won = self.hits >= self.hitsForWin
		taskSystem:cancelAllTasksFor(self.connor.character)
		self.connor.character:addTask({class="SetTask", baseAnimation="CONNOR"})
		self.connor.character:addTask({class="SetTask", state="", clickable=true})
		self.connor.character:addTask({class="SetTask", clickable=false, direction="down"})
		self.connor.character:addTask({class="PlayAnimationTask", animation="IDLE"})

		eventBar:deactivate()

		if (isTable(taskSystem:getAnimationDesc("eventWon"))) then
			return taskSystem:createAnimation("eventWon")
		end
	end
end

function SpecialRoom3:stopWaving()
	self.waving = false
	self.timer = self.timeBetweenWaves
	taskSystem:cancelAllTasksFor(self.connor.character)
	taskSystem:cancelAllTasksFor(self.extraCharacters[1])
	taskSystem:cancelAllTasksFor(self.extraCharacters[2])
	self:addWalkToTask()

	hintManager:removeArrows({id="ball_event"})
end

function SpecialRoom3:onStart()
	self.started = true

	self.extraCharacters = {level:getCharacter("girl"), level:getCharacter("boy3")}
	for i=1, 2 do
		self.extraCharacters[i].walkSpeed = 320
	end
	
	self.timer = self.timeBetweenWaves
	self.connor.character.playIdleAnimations = false
	self.connor.character.onClick = SpecialRoom3.onClick
	self:addWalkToTask()
	
	eventBar:activate()
end

function SpecialRoom3:onClick()
	if (self.state == STATE_STILL) then
		level.event:throwBall()
		hintManager:removeArrows({id="connorArrow"})
		return true
	end
end

function SpecialRoom3:getDist(x1,x2,y1,y2)
	local dx = x2-x1
	local dy = y2-y1
	local dist = math.sqrt((dx*dx+dy*dy))
	return dist
end

function SpecialRoom3:throwBall()
	self.ballsThrown = self.ballsThrown + 1
	
	eventBar:incValue(1)
	
	taskSystem:cancelAllTasksFor(self.connor.character)
	self.connor.character:playAnimation("WAVE_ARMS#LEFT")
	self.connor.character.clickable = false
	
    if (isTable(taskSystem:getAnimationDesc("eventThrow"))) then
        return taskSystem:createAnimation("eventThrow")
    end
end

function SpecialRoom3:handleTrigger(trigger, meta)

	if (trigger == "startThrow") then
		self.connor.character:playAnimation("IDLE")
		local xStart = hero.x - 30
		local yStart = hero.y-180

		local desc = {
			class = "LuaBall",
			name="ball"..self.ballsThrown,
			x=xStart,
			y = yStart,
			floor = 400,
			baseAnimation = "EVENT_SPECIAL_BALL_"..((self.ballsThrown%3)+1),
			visible=true,
			startX=xStart,
			stopX=self.connor.character.x + 80,
			startY=yStart,
			stopY=self.connor.character.y-200,
		}

		local obj = level:add(desc)
		SpecialRoom3.balls["ball"..self.ballsThrown] = obj

		--score!
		self.hits = self.hits + 1
		return true
	elseif (trigger == "endThrow") then
		local loc = self.connor.character.location
		level:addHeartsWithFloater(self.scoreOneDone, loc.x, loc.y - self.connor.character.height, false)
		self:stopWaving()
	end

	return SpecialRoom3.super.handleTrigger(self, trigger, meta)
end

--************  LUA BALL  *******************--
LuaBall = deriveLuaClass("LuaBall", "Object")

LuaBall.startX = 0
LuaBall.startY = 0
LuaBall.stopX = 0
LuaBall.stopY = 0

LuaBall.dist = 0.0
LuaBall.raised = 0
LuaBall.completed = false
LuaBall.timer = 0
LuaBall.duration = 450
LuaBall.curve = 30
LuaBall.bp0 = {}
LuaBall.bp1 = {}
LuaBall.bp2 = {}
LuaBall.bp3 = {}

function LuaBall:init(desc)
	LuaBall.superInit(desc)

	self.bp0 = {x=self.startX, y=self.startY}
	self.bp1 = {x=self.startX, y=self.startY - self.curve}
	self.bp2 = {x=self.stopX, y=self.stopY - self.curve}
	self.bp3 = {x=self.stopX, y=self.stopY}
end

function LuaBall:onTick(time)
	self.timer = self.timer + time
	if (self.completed) then
		return
	end
	local curDist = self:getDist(self.x, self.stopX, self.y, self.stopY)
	local percCompleted = self.timer/self.duration
	if (percCompleted > 1) then
		self.floor = -10
		self.completed = true
		self:setObsolete(true)
		return
	end

	local p = self:BezierPoint(self.bp0, self.bp1, self.bp2, self.bp3, percCompleted)
	self.y = p.y
	self.x = p.x
end

function LuaBall:getDist(x1,x2,y1,y2)
	local dx = x2-x1
	local dy = y2-y1
	local dist = math.sqrt((dx*dx+dy*dy))
	return dist
end

Point = {}
Point.mt = {}

Point.mt.__add =
function(a,b)
	 local c = {x=0,y=0}
	 setmetatable(c, Point.mt)
	 c.x = a.x + b.x
	 c.y = a.y + b.y
	 return c
end

Point.mt.__mul =
function(a,b)
	local c = {x=0,y=0}
	setmetatable(c, Point.mt)
	if (isNumber(a)) then
		c.x = a * b.x
		c.y = a * b.y
	 else
		 c.x = b * a.x
		 c.y = b * a.y
	end
	return c
end

function LuaBall:BezierPoint(p0,p1,p2,p3,t)

	setmetatable(p0, Point.mt)
    setmetatable(p1, Point.mt)
    setmetatable(p2, Point.mt)
    setmetatable(p3, Point.mt)

    local b1 = math.pow((1-t),3)*p0
    local b2 = 3*math.pow((1-t),2)*t*p1
    local b3 = 3*(1-t)*math.pow(t,2)*p2
    local b4 = math.pow(t,3)*p3

	return b1+b2+b3+b4
end