:NAME shield

:PARAM float32				duration
:PARAM s_ping_effect@		ping
:PARAM s_color				freeze_tint
:PARAM float32				color_transition_time

:ENEMY c_object*			object
:ENEMY boolean				has_tint
:ENEMY boolean				is_turret
:ENEMY boolean				is_camera

:VAR enemy[]		enemies
:VAR boolean		pinged
:VAR boolean		played_melt_sound
:VAR c_object*		matte

-- ------------------- constants ------------------- 

k_bar_width= 1
k_bar_height= 0.25
k_y_offset= 0.4

k_bar_color= {}
k_bar_color.red= 0.85			-- 1
k_bar_color.blue= 0				-- 1
k_bar_color.green= 0.17			-- 0

k_empty_color={}
k_empty_color.red= 0.0			-- 0.2
k_empty_color.blue= 0.0			-- 0.2
k_empty_color.green= 0.0		-- 0.0

k_default_radius= 2

k_melt_sound_duration= 1

local vectorlib = require "scripts/vector_math"


-- ------------------- initialization ------------------- 

function param_initialize(p)
	p.duration = 2	
end

function var_initialize(v)
	v.pinged= false
	v.matte= nil
	v.played_melt_sound= false
end


-- ------------------- component ------------------- 


function draw_timer(object, dt)
	local base_point = object.world_position_get()

	base_point.x = base_point.x - k_bar_width/2
	base_point.y = base_point.y + k_y_offset
	
	local top_left= {}
	top_left.x= base_point.x
	top_left.y= base_point.y + k_bar_height
	
	local end_point= {}
	end_point.x = base_point.x + k_bar_width
	end_point.y = base_point.y
	
	render_rectangle(object.plate, top_left, end_point, k_empty_color, true)

	local fraction= 1 - dt/param.duration	
	end_point.x = base_point.x + fraction*k_bar_width
	
	render_rectangle(object.plate, top_left, end_point, k_bar_color, true)

end

function attach(object)
	local ws= world_state_get()
	
	-- collect a list of all enemies
	local iterator= ws.component_cache.component_perception.iterator_get()
	while (true) do
		local perception= iterator.next()
		if (perception) then
			local enemy = var.enemies.create()
			if (enemy) then
				local enemy_object= perception.object
				
				local turret_aim= enemy_object.turret_aim_get()
				local camera_behavior= enemy_object._c.camera_behavior
				
				enemy.object= enemy_object
				enemy.has_tint= (enemy_object.tint_get()~=nil)
				enemy.is_turret= (turret_aim~=nil)
				enemy.is_camera= (camera_behavior~=nil)

				if (turret_aim) then
					turret_aim.frozen= true
				elseif (camera_behavior) then
					camera_behavior.frozen= true
				else
					local path_follow= enemy_object.path_follow_get()
					if (path_follow) then
						path_follow.freeze(param.duration)
						
						-- put a timer on them?
					end
				end
			end
		else
			break
		end
	end
	
	-- set all targetable targets as unperceivable
	local target_iterator= ws.targets.iterator_get()
	while (true) do
		local target= target_iterator.next()
		if (target) then
			if (target.is_targetable()) then
				target.set_unperceivable(true)
			end
		else
			break
		end
	end
	
	-- place the freeze matte
	var.matte= ws.place_by_plate("screen_effects", "freeze_matte")
	
	-- play start sound
	local sound= object.sound_get()
	if (sound) then
		sound.play_sound("start", false);
	end
	
end

function color_enemies(t, color)
	local iterator= var.enemies.iterator_get()
	while (true) do
		local enemy= iterator.next()
		if (enemy) then
			if (enemy.has_tint) then
				-- anything?
				-- note, this assumes that this is the ONLY thing tinting characters
				local tint= enemy.object.tint_get()
				if (tint) then
					local one_minus_t= 1-t
					local tint_color= tint.tint
					tint_color.red= t*color.red + one_minus_t
					tint_color.green= t*color.green + one_minus_t
					tint_color.blue= t*color.blue + one_minus_t
				end
			end
		else
			break
		end
	end

end


function finish(object)

	local ws= world_state_get()

	-- anything we need to reset on the enemies?
	local iterator= var.enemies.iterator_get()
	while (true) do
		local enemy= iterator.next()
		if (enemy) then
			-- reset anything?
			if (enemy.is_turret) then
				local turret_aim= enemy.object.turret_aim_get()
				turret_aim.frozen= false
			elseif (enemy.is_camera) then
				local camera_behvior= enemy.object._c.camera_behavior
				camera_behvior.frozen= false
			end
		else
			break
		end
	end

	-- set all targetable targets as unperceivable
	local target_iterator= ws.targets.iterator_get()
	while (true) do
		local target= target_iterator.next()
		if (target) then
			if (target.is_targetable()) then
				target.set_unperceivable(false)
			end
		else
			break
		end
	end
	
	color_enemies(0, param.freeze_tint)
	
	if (var.matte) then
		if (not var.matte.tween_animation_play("end")) then
			object_delete(var.matte)
		end
	end

	object_delete(object)
end

function update(object)
	
	local ws= world_state_get()
	local time= ws.time.time		
	local dt= time-object.placement_time
	
	if (dt < param.duration) then

		local iterator= var.enemies.iterator_get()
		while (true) do
			local enemy= iterator.next()
			if (enemy) then
				draw_timer(enemy.object, dt)
			else
				break
			end
		end
		
		local t= 1		
		if (dt < param.color_transition_time) then
			t= dt/param.color_transition_time
		elseif (dt > (param.duration-param.color_transition_time)) then
			t= 1 - (dt - param.duration + param.color_transition_time)/param.color_transition_time
		end
		color_enemies(t, param.freeze_tint)
		
		if ((not var.played_melt_sound) and (dt > (param.duration-k_melt_sound_duration))) then
			local sound= object.sound_get()
			if (sound) then
				sound.play_sound("end", false)
			end
			var.played_melt_sound= true
		end
		
	else
		finish(object)
	end

	if (not var.pinged and param.ping) then
	
		local dmap_component = object.distance_map_get()
		if (dmap_component) then
			local pos= object.world_position_get()
			dmap_component.compute_at_point(pos.x, pos.y)
			
			local dmap= dmap_component.distance_map
			if (dmap.valid()) then
				dmap.ping(param.ping)
			end
			var.pinged= true
		end

		--[[
		local parent= object.attachment.parent
		if (parent) then
			local target= parent.target_get()
			if (target and (not target.is_distance_map_dirty())) then
				local distance_map= target.distance_map
				if (distance_map.valid()) then
					distance_map.ping(param.ping)
					var.pinged= true
				end
			end
		end
		--]]
	end
end

component_register(attach, update, nil, nil)
