--
-- The game mode
--

-- Called every frame (game)
function update_game( time_step )
	world_update( time_step, keys.lpad, keys.rpad )

	-- Camera update
	local plr_pos = Vec2( -100, -100 )
	for k,v in balls do
		local ball_pos = ObjectGetPos( (SceneGetObjects( v )) )
		if ball_pos.y > plr_pos.y then plr_pos = ball_pos end
	end
	if plr_pos.y == -100 then plr_pos = CamGet() end

	local new_cam_pos = plr_pos - Vec2( 400, 300 )
	CamSet( CamGet() * 0.98 + new_cam_pos * 0.02 )

	if not had_push and keys.push then push_world() end
	had_push = keys.push

	-- Launching the ball
	if scene_launching then
		if HudIsClear() then
			HudScrollText( "Player " .. (cur_plr+1) .. ", ball " .. (cur_ball+1) .. "      Hit enter to launch the ball!", 50 )
		end

		-- Launching it?
		if not had_launch and keys.launch then
			scene_launching = false
	
			HudClear()
			launch_ball( balls[1] )
		end
	end
	had_launch = keys.launch

	if scene_launching then return end

	-- Add acceleration to the wheels?
	if scene_wheel_accel > 0 then
		scene_wheel_accel = scene_wheel_accel - time_step
		ObjectAddTorque( SceneGetObjectsById( main_scene, "right_wheel" ), 1600 )
		ObjectAddTorque( SceneGetObjectsById( main_scene, "center_wheel" ), 1600 )
		ObjectAddTorque( SceneGetObjectsById( main_scene, "left_wheel" ), 1600 )
	end

	-- Ball save timeout?
	if not scene_launching and ball_save_timeout > 0 then
		ball_save_timeout = ball_save_timeout - time_step
	end

	-- Respawn the ball?
	if scene_respawn then
		scene_respawn = false
		local ball = spawn_ball( ball_scene_ids[ plr.ball_type ] )
		launch_ball( ball )
	end

	-- Multiballs?
	if plr.multiballs > 0 then
		plr.multiball_time = plr.multiball_time -time_step
		if plr.multiball_time <= 0 then
			plr.multiballs = plr.multiballs - 1
			plr.multiball_time = 4

			-- Spawn the ball
			local ball = spawn_ball( ball_scene_ids[ plr.ball_type ] )
			launch_ball( ball )
		end
	end

	-- Update the HUD
	HudSetScore( cur_plr, plr.score )

	-- Change players?
	if table.size(balls) <= 0 and plr.multiballs <= 0 then
		scene_next_player = false
		next_player()
		return
	end

	-- Update the game mode
	cur_mode:update( time_step )
end

-- Called when a trigger is entered (by an object)
function game_trigger_object_enter( trig_scene, trig_obj, scene, obj )
--	print( "TRIGGER OBJ ENTER (" .. trig_obj .. "/" .. trig_scene .. "): " .. obj .. "/" .. scene )
	local trig_id = ObjectGetGameId( trig_obj )

	if scene_tilt then return end

	local is_plr_scene = is_ball_scene( scene )

	-- Bouncers
	if is_plr_scene and (trig_id == "bouncer01_trigger" or trig_id == "bouncer02_trigger" or trig_id == "bouncer03_trigger") then
		SoundPlay( "kilikili.wav" )
		apply_away_force( scene, ObjectGetPos( trig_obj ), 42000 )

		plr.score = plr.score + 1000
		do_blink( trig_obj, 0.1 )

		cur_mode:bouncer_hit()
	end

	-- Switch
	if trig_id == "SwitchTrigger" then
		SoundPlay( "02_kytkin.wav" )
		HudScrollText( "Turn on!!", 100, 1 )
		if scene_wheel_accel < 2.0 then scene_wheel_accel = 2.0 end

		cur_mode:switch_hit()

		-- Advance the lights
		local count = objs_count_lit( swlamp_objs )
		local max = table.getn( swlamp_objs )

		if count >= max then
			objs_set_lit( swlamp_objs, false )
			cur_mode:switch_lights_done()
		else
			objs_set_lit_amt( swlamp_objs, count + 1 )
		end
		
	end
end

-- Called when a trigger is exited (by an object)
function game_trigger_object_exit( trig_scene, trig_obj, scene, obj )
--	print( "TRIGGER OBJ EXIT (" .. trig_obj .. "/" .. trig_scene .. "): " .. obj .. "/" .. scene )
end

-- Called when a trigger is entered (by an object)
function game_trigger_scene_enter( trig_scene, trig_obj, scene )
--	print( "TRIGGER SCENE ENTER (" .. trig_obj .. "/" .. trig_scene .. "): " .. scene )
	local trig_id = ObjectGetGameId( trig_obj )
	local trig_lit = ObjectIsLit( trig_obj )

	local is_plr_scene = is_ball_scene( scene )

	-- Fall out?
	if ( is_plr_scene and trig_id == "FallOut" ) then
		SoundPlay( "06_uusipelaaja.wav" )
		set_playmode( mode_normal )
		remove_ball( scene )
		return
	end

	-- TILT??
	if scene_tilt then return end

	-- Launch chute; top?
	if is_plr_scene and trig_obj == obj_launch_top then
		ball_launch_top( scene )
		return
	end

	-- Launch chute; bottom?
	if is_plr_scene and trig_obj == obj_launch_bottom then
		ball_launch_bottom( scene )
		return
	end

	-- Down the shutes?
	if is_plr_scene and trig_id == "DownShute" then
		SoundPlay( "05_pallokouruun.wav" )
		plr.score = plr.score + 3000

		if HudIsClear() then
			HudScrollText( "Down the chute!", 100 )
		end
		return
	end

	-- Big red button?
	if is_plr_scene and trig_obj == obj_red_button then
		SoundPlay( "07_magneetti.wav" )
		plr.score = plr.score + 4000
		do_blink( trig_obj, 0.2 )
		cur_mode:red_button_hit()
		return
	end

	-- Crate?
	if is_plr_scene and trig_id == "crate" then
		SoundPlay( "high_thumb.wav" )
		plr.score = plr.score + 1500
		do_blink( trig_obj, 0.2 )
		cur_mode:crate_hit()
		return
	end

	-- Flame triggers?
	if is_plr_scene and table.contains_value( flame_objs, trig_obj ) then
		SoundPlay( "17_hit_05.wav" )
		if not trig_lit then
			plr.score = plr.score + 2000
			ObjectSetLit( trig_obj, true )
		end

		-- All are lit?
		if objs_are_lit( flame_objs ) then
			plr.score = plr.score + 2000
			objs_set_lit( flame_objs, false )
			cur_mode:flame_done()
		end
		return
	end

	-- Rollpad triggers?
	if is_plr_scene and table.contains_value( rollpad_objs, trig_obj ) then
		SoundPlay( "14_hit_02.wav" )
		if not trig_lit then
			plr.score = plr.score + 250
			ObjectSetLit( trig_obj, true )
		end

		cur_mode:rollpad_hit()

		-- All are lit?
		if objs_are_lit( rollpad_objs ) then
			plr.score = plr.score + 5000
			objs_set_lit( rollpad_objs, false )
			cur_mode:rollpad_done()
		end
		return
	end

	-- Hazard triggers
	if is_plr_scene and table.contains_value( hazard_objs, trig_obj ) then
		SoundPlay( "beeb.wav" )

		if trig_lit then
			plr.score = plr.score + 1000
		else
			plr.score = plr.score + 15000
			HudShowText( string.sub( trig_id, 8, 8 ), 2, 0.15 )
		end
		ObjectSetLit( trig_obj, true )

		cur_mode:hazard_hit()

		-- All letters collected?
		if objs_are_lit( hazard_objs ) then
			plr.score = plr.score + 350000
			objs_set_lit( hazard_objs, false )
			cur_mode:hazard_done()
		end
		return
	end

	-- Factory triggers
	if is_plr_scene and table.contains_value( factory_objs, trig_obj ) then
		SoundPlay( "beeb.wav" )
		if trig_lit then
			plr.score = plr.score + 1000
		else
			plr.score = plr.score + 15000
			HudShowText( string.sub( trig_id, 9, 9 ), 2, 0.15 )
		end
		ObjectSetLit( trig_obj, true )

		cur_mode:factory_hit()

		-- All letters collected?
		if objs_are_lit( factory_objs ) then
			plr.score = plr.score + 550000
			objs_set_lit( factory_objs, false )
			cur_mode:factory_done()
		end
		return
	end

	-- Left vault
	if is_plr_scene and trig_id == "LeftVault" then
		SoundPlay( "04_vault.wav" )
		plr.score = plr.score + 60000
		HudScrollText( "Switch characters!", 75 )

		plr.ball_type = plr.ball_type - 1
		if plr.ball_type <= 0 then plr.ball_type = table.getn(ball_scene_ids) end
		remove_ball( scene )
		scene_respawn = true
		return
	end

	-- Right vault
	if is_plr_scene and trig_id == "RightVault" then
		SoundPlay( "04_vault.wav" )
		plr.score = plr.score + 60000
		HudScrollText( "Switch characters!", 75 )

		plr.ball_type = plr.ball_type + 1
		if plr.ball_type > table.getn(ball_scene_ids) then plr.ball_type = 1 end
		remove_ball( scene )
		scene_respawn = true
		return
	end
end

-- Called when a trigger is exited (by an object)
function game_trigger_scene_exit( trig_scene, trig_obj, scene )
--	print( "TRIGGER SCENE EXIT (" .. trig_obj .. "/" .. trig_scene .. "): " .. scene )
end

-- Called when an object rotates
function game_object_rotated( scene, obj, rot_amt )
	local id = ObjectGetGameId( obj )

	if id == "" or scene_tilt then return end

	if id == "left_wheel" or id == "center_wheel" or id == "right_wheel" or id == "RollingPad" then
		SoundPlay( "low_pojong.wav" )
		plr.score = plr.score + 500
		cur_mode:wheel_click()
	end
end

-- Updates the "accident" letters
function update_accident_letters( add )
	plr.accident = plr.accident + add 

	-- Done?
	local amt = table.getn(accident_ids)
	if plr.accident >= amt then
		plr.score = plr.score + 1000000
		plr.accident = 0

		cur_mode:accident_done()
	end

	-- Update the letters
	objs_set_lit_amt( accident_objs, plr.accident )
end

-- Resets the world for a new ball and player
function new_player_turn()
	plr = players[ cur_plr ]

	ball_save_timeout = 10

	plr.extra_balls = 0
	plr.multiballs = 0
	plr.multiball_time = 0

	-- Reset the world
	reset_world()

	for k,v in all_modes do v:new_player() end
	set_playmode( mode_normal )

	-- Update the accident letters
	update_accident_letters( 0 )

	-- Spawn a new ball
	spawn_ball( ball_scene_ids[ plr.ball_type ] )
	scene_launching = true
end

-- Moves on to the next player/ball
function next_player()
	-- Ball saved?
	if ball_save_timeout > 0 then
		HudScrollText( "BALL SAVED!", 100 )

		spawn_ball( ball_scene_ids[ plr.ball_type ] )
		scene_launching = true
		return
	end

	-- Use an extra ball?
	if plr.extra_balls > 0 then
		plr.extra_balls = plr.extra_balls - 1
		HudScrollText( "SHOOT AGAIN!", 100 )

		spawn_ball( ball_scene_ids[ plr.ball_type ] )
		scene_launching = true
		return
	end

	-- Clear the play mode
	set_playmode( mode_normal )

	HudClear()

	-- Next player and/or ball?
	cur_plr = cur_plr + 1
	if cur_plr >= players.count then
		cur_plr = 0
		cur_ball = cur_ball + 1
	end

	-- End of game?
	if cur_ball >= 3 then
		-- Collect the scores
		local scores = {}
		for i = 0,players.count-1 do
			scores[ i+1 ] = players[ i ].score
		end

		-- Go to the hiscore screen
		setup_hiscore( scores )
		return
	end

	-- New turn
	print( "Player " .. (cur_plr+1) .. ", ball " .. (cur_ball+1) )
	new_player_turn()
end

-- Sets up the game to the game mode
function setup_game( plr_count )
	print( "Game mode" )
	MusicPlay( "game.ogg" )

	spawn_world()

	HudClear()
	HudSetPlayers( plr_count )
	players = { count = plr_count }
	for i = 0,plr_count-1 do
		local p = {}
		p.ball_type = 1
		p.score = 0
		p.accident = 0
		players[ i ] = p

		HudSetScore( i, p.score )
	end

	-- Set the callbacks
	reset_callbacks()
	update = update_game
	trigger_object_enter = game_trigger_object_enter
	trigger_object_exit = game_trigger_object_exit
	trigger_scene_enter = game_trigger_scene_enter
	trigger_scene_exit = game_trigger_scene_exit
	object_rotated = game_object_rotated

	-- Start the game
	ball_save_timeout = 0

	cur_ball = 0
	cur_plr = 0
	new_player_turn()
end
