bonus = {}

bonus.simple_ball_effects = {shrink_ball = true, grow_ball = true} --CEffect
bonus.ball_effects = {  gold_ball = true, bonus_brick_ball = true, 
						fast_ball = true, slow_ball = true} --CBallEffect
bonus.simple_board_effects = {shrink_board = true, expand_board = true, bonus_magnet = true}
bonus.board_effects = {aim_ball = true, balls_magnet = true, ball_catcher = true,
						chain_lighting_gun = true, laser_gun = true, 
						cannon = true,
						flame_thrower = true,
						rockets = true,
						mine = true,
						droid = true,
						force_field = true,
						life_loss = true} --CBoardEffect				 
bonus.level_effects = {three_ball_split = true, super_three_ball_split = true,  
							eight_ball_split = true, barrier = true, balloons = true,
							gravitation_ball = true, anti_gravitation_ball = true,
							indestructible_explosion = true,
							extra_points = true,
							laser_shock = true,
							horizontal_lighting = true, vertical_lighting = true,
							nuke = true,	
							fire_ball = true,
							rail_ball = true,
							air_ball = true,
							vacuum_ball = true,
							crazy_ball = true,
							angry_ball = true,
							plasma_ball = true,
							detonate_ball = true}

local table_concat = function(_left, _right)
	local arr = {}
	for k,v in pairs(_right) do
		arr[k] = v
	end
	for k,v in pairs(_left) do
		arr[k] = v
	end	
	return arr
end

bonus.all_effects = table_concat(bonus.level_effects, 
						table_concat(bonus.simple_board_effects,
							table_concat(bonus.board_effects,
								table_concat(bonus.ball_effects, bonus.simple_ball_effects))))

local add_ball_effect = function(_id)
	local ball = game.g_Level.GetBalls()
	while not ball.IsEnd() do 
		local bonus_effect = s4.g_EffectsFactory.Instance().CreateAndLoadEffect(_id)
		ball.Get().get().AddBallEffect(s4.CBallEffectPtrT(__cast(bonus_effect.get(), "s4.CBallEffect")))
		ball.Next()
	end	
	collectgarbage()
end
								
function bonus.apply_bonus_effect(bonus_id)
	if not bonus.all_effects[bonus_id] then
		log("Unknown bonus id '"..bonus_id.."'", sf.core.CLogClient.Error)
		return
	end
		
	if bonus.simple_ball_effects[bonus_id] then
		local ball = game.g_Level.GetBalls()
		while not ball.IsEnd() do 
			local bonus_effect = s4.g_EffectsFactory.Instance().CreateAndLoadEffect(_T(bonus_id.."_effect"))
			ball.Get().get().AddEffect(bonus_effect)
			ball.Next()
		end							
		ball = game.g_Level.GetInvisibleBalls()
		while not ball.IsEnd() do 
			local bonus_effect = s4.g_EffectsFactory.Instance().CreateAndLoadEffect(_T(bonus_id.."_effect"))
			ball.Get().get().AddEffect(bonus_effect)
			ball.Next()
		end							
		
	elseif bonus.ball_effects[bonus_id] then
		add_ball_effect(_T(bonus_id.."_effect"))

	elseif bonus.simple_board_effects[bonus_id] then 
		local bonus_effect = s4.g_EffectsFactory.Instance().CreateAndLoadEffect(_T(bonus_id.."_effect"))
		game.g_Level.GetBoard().AddEffect(bonus_effect)	
		
	elseif bonus.board_effects[bonus_id] then 
		local bonus_effect = s4.g_EffectsFactory.Instance().CreateAndLoadEffect(_T(bonus_id.."_effect"))
		game.g_Level.GetBoard().AddBoardEffect(
			s4.CBoardEffectPtrT(__cast(bonus_effect.get(), "s4.CBoardEffect")))
		
	elseif bonus.level_effects[bonus_id] then 
		local bonus_effect = s4.g_EffectsFactory.Instance().CreateAndLoadEffect(_T(bonus_id.."_effect"))
		game.g_Level.AddEffect(bonus_effect) 
	end
	
	collectgarbage()
end

function bonus.apply_weapon_effect(bonus_id)
	if not bonus.all_effects[bonus_id] then
		log("Unknown bonus id '"..bonus_id.."'", sf.core.CLogClient.Error)
		return
	end
		
	if bonus.board_effects[bonus_id] then 
		local bonus_effect = s4.g_EffectsFactory.Instance().CreateAndLoadEffect(_T("weapon_transform_effect"))
		
		local weapon_transform_effect = __cast(bonus_effect.get(), "s4.CWeaponTransformEffect")
		weapon_transform_effect.SetWeaponEffectId(_T(bonus_id.."_effect"))
		
		game.g_Level.GetBoard().AddBoardEffect(
			s4.CBoardEffectPtrT(__cast(bonus_effect.get(), "s4.CBoardEffect")))
	end
	collectgarbage()
end
--[[
local ball_split = function(_num, _tangle)
	local ball = game.g_Level.GetBalls()

	if ball.IsEnd() then return end
	
	local current_ball = ball.Get().get()
	local velocity_vector = current_ball.GetVel()
	local vel_module = math.sqrt (velocity_vector.X * velocity_vector.X + velocity_vector.Y * velocity_vector.Y)
	local dx = velocity_vector.X / vel_module
	local dy = velocity_vector.Y / vel_module
	local i = 1
	while i ~= (_num + 1) do 
		local new_ball = current_ball.Clone()
		local delta_fi = ((i*_tangle)/360.0) * (3.1415 * 2)
		new_ball.get().SetDirection( dx * math.cos(delta_fi) - dy * math.sin(delta_fi) , dy * math.cos(delta_fi) + dx * math.sin(delta_fi))
		game.g_Level.AddBall(new_ball)
		i = i + 1
	end
end
]]
function bonus.extra_life()
	--local player = game.g_Level.GetPlayer()
	--player.SetLives(player.GetLives() + 1)
	--local main_window = sf.core.g_Application.GetMainWindow()
	 --__cast(main_window, s4.CGameWindow)
	local game_window = game.g_Level.GetGameWindow()
	game_window.AddLivesToPlayer(1);
	
end
--[[
function bonus.life_loss()
	local bonus_effect = s4.g_EffectsFactory.Instance().CreateAndLoadEffect(_T("dead_board_effect"))
	game.g_Level.GetBoard().AddBoardEffect(
		s4.CBoardEffectPtrT(__cast(bonus_effect.get(), "s4.CBoardEffect")))


	local board = game.g_Level.GetBoard()
	if board then
		board.SetAlpha(50)
		board.SetIgnorePhysObjects(true)
--		board.SetDead(true)
	end	
end
]]
function bonus.warp_level()
	local board = game.g_Level.SetComplete()
end
--[[
function bonus.three_ball_split()
	ball_split(2, 120)
	collectgarbage()
end

function bonus.eight_ball_split()
	ball_split(7, 45)
	collectgarbage()
end

function bonus.super_three_ball_split()
	if true then
		local add_delat_fi = 120
		local num_new_balls = 2
		local new_balls_array = {}
		local array_uk = 0
		local ball = game.g_Level.GetBalls()
		while not ball.IsEnd() do 
			local current_ball = ball.Get().get()
			local velocity_vector = current_ball.GetVel()
			local vel_module = math.sqrt (velocity_vector.X * velocity_vector.X + velocity_vector.Y * velocity_vector.Y)
			local dx = velocity_vector.X / vel_module
			local dy = velocity_vector.Y / vel_module
			local i = 1
			while i ~= (num_new_balls+1) do 
				local new_ball = current_ball.Clone()
				local delta_fi = ((i*add_delat_fi)/360.0) * (3.1415 * 2)
				new_ball.get().SetDirection( dx * math.cos(delta_fi) - dy * math.sin(delta_fi) , dy * math.cos(delta_fi) + dx * math.sin(delta_fi))
				new_balls_array[array_uk] = new_ball
				i = i + 1
				array_uk = array_uk + 1
			end
			ball.Next()
		end
		local i = 0
		while i ~= array_uk do 
			game.g_Level.AddBall(new_balls_array[i])
			i = i + 1
		end
	end
	collectgarbage()
end
]]