--[[------------------------------------------------------------------------------------------------------------------
Проигровка звуков при входе актёра в рестриктор.
Чугай Александр

Sliding sound support: Jim
--------------------------------------------------------------------------------------------------------------------]]

-- типы звуков для зон
local sound_types = {
	floor_wooden = {
		"ambient\\floor_creak1",
		"ambient\\floor_creak2",
		"ambient\\floor_creak3"
	},
	rats_panic = {
		"ambient\\rats_panic_1",
		"ambient\\rats_panic_2",
		"ambient\\rats_panic_3"
	},
	random = {
		"ambient\\random\\new_drone1",
		"ambient\\random\\new_drone2",
		"ambient\\random\\rnd_3dmbridge",
		"ambient\\random\\rnd_ak47_1",
		"ambient\\random\\rnd_ak47_2",
		"ambient\\gunfire_1",
		"ambient\\gunfire_2",
		"ambient\\random\\rnd_crow",
		"ambient\\random\\rnd_disgusting",
		"ambient\\random\\rnd_distantmortar3",
		"ambient\\random\\rnd_dog6",
		"ambient\\random\\rnd_drone1",
		"ambient\\random\\rnd_drone2",
		"ambient\\random\\rnd_fallscream",
		"ambient\\random\\rnd_horror3",
		"ambient\\random\\rnd_horror4",
		"ambient\\random\\rnd_m-16_3",
		"ambient\\random\\rnd_m-16_4",
		"ambient\\random\\rnd_m-249",
		"ambient\\random\\rnd_moan",
		"ambient\\random\\rnd_moan1",
		"ambient\\random\\rnd_moan2",
		"ambient\\random\\rnd_moan3",
		"ambient\\random\\rnd_moan4",
		"ambient\\random\\rnd_moan5",
		"ambient\\random\\rnd_scr1",
		"ambient\\random\\rnd_scr2",
		"ambient\\random\\rnd_scr3",
		"ambient\\random\\rnd_scr4",
		"ambient\\random\\rnd_scr5",
		"ambient\\random\\rnd_scr7",
		"ambient\\random\\rnd_scr8",
		"ambient\\random\\rnd_scr9",
		"ambient\\random\\rnd_scr10",
		"ambient\\random\\rnd_the_horror1",
		"ambient\\random\\rnd_the_horror2",
		"ambient\\random\\rnd_the_horror3",
		"ambient\\random\\rnd_the_horror4",
		"ambient\\random\\rnd_thunder",
		"ambient\\random\\rnd_wolfhowl01",
		"ambient\\random\\rnd_wolfhowl02",
		"ambient\\random\\rt_coo1-m",
		"ambient\\random\\rt_sickened1",
		"ambient\\random\\rt_sickened2",
		"ambient\\random\\rt_swamp_thing1"
	}
}

local pos_path   = 0
local pos_random = 1
local pos_obj    = 2

-- включить в dest все элементы из src. Таблицы индексированы
function table_include( dest, src )
	if dest and src then
		for i, v in pairs(src) do
			table.insert( dest, v )
		end
	end
end

----------------------------------------------------------------------------------------------------
class "action_sound"

function action_sound:__init( obj, storage )
	self.object = obj
	self.st = storage

	self.is_actor_inside = nil
end

function action_sound:reset_scheme()
	--printf("_bp: sr_idle: action_sound:reset_scheme: self.object:name()='%s'", self.object:name())

	self.st.idle_end = 0
	self.st.signals = {}
	self.is_actor_inside = false
	--if self.snd_obj ~= nil then
	   --self.snd_obj:stop()
	--end    
	self.snd_obj = nil
	
	self.slide_active = false

end

function action_sound:update( delta )
	
	-- check for update of sliding sound
	if self.slide_active and not self.snd_obj:playing() and self.st.sound_slide_once then
		self.slide_active = false
	end
	
	if self.slide_active then
		-- play sound
		if not self.snd_obj:playing() then 
			self.snd_obj:play_at_pos(self.object, self.current, self.st.delay)
		else 
			self.snd_obj:set_position(self.current)	
		end
		
		-- update current position
		local target_pos = vector():set(self.current)
		target_pos:mad(self.dir, self.st.sound_slide_vel * delta / 1000)
		
		if target_pos:distance_to(self.current) > self.current:distance_to(self.target) then
			self.cur_point	= self:next_point()
			self:set_positions()
		else
			self.current	= vector():set(target_pos)
		end
	end
	---------------------------------------
	
	local actor = db.actor
	-- если мы ещё нигде, то не считать ни входа, ни выхода
	if self.is_actor_inside == nil then
		self.is_actor_inside = self.object:inside( actor:position() )
		return
	end

	if self.object:inside( actor:position() ) then
		if not self.is_actor_inside then
			self:on_enter( actor )
			self.is_actor_inside = true
		end
        if self.snd_obj ~= nil and self.snd_obj:playing () == false then
		   self.st.signals["sound_end"] = true
		end    
	else
		if self.is_actor_inside then
			--self.on_leave( actor )
			self.is_actor_inside = false
		end
	end

	xr_logic.try_switch_to_another_section( self.object, self.st, actor )
end


function action_sound:on_enter( obj )
	if self.st.idle_end < game.time() then
		self.st.idle_end = game.time() + self.st.idle
		if math.random( 100 ) <= self.st.rnd then
			local pos

			if self.st.pos_type == pos_obj then
				pos = obj:position()
			elseif self.st.pos_type == pos_random then
				local ang = math.pi / 180.0 * math.random( 0, 35900 ) * 0.01
				pos:add( vector():set( math.cos( ang ), 0, math.sin( ang ) ):mul( math.random( 1500, 5000 ) * 0.01 ) )
--				printf( "%f", obj:position():distance_to( pos ) )
			elseif self.st.pos_type == pos_path then
				
				if not self.st.sound_slide then
					pos = self.st.path:point( math.random( 0, self.st.path:count()-1 ) )
				else 
					self.slide_active = true
					self.cur_point	  = 0
					self:set_positions()
					pos = self.st.path:point(self.cur_point)
				end
					
			end

			local snd_name = self.st.sound_names[math.random(1, #self.st.sound_names]
			printf( "sr_sound: restrictor=%s pos_type=%d snd=%s", self.object:name(), self.st.pos_type, snd_name )

			self.snd_obj	= xr_sound.get_safe_sound_object(snd_name)
	        if self.st.play_at_actor == false then
			   self.snd_obj:play_at_pos( obj, pos, self.st.delay )
			else
			   self.snd_obj:play_at_pos( obj, vector ():set (0, 0, 0), self.st.delay, sound_object.s2d )
			end   
			printf ("SOUND PLAY %s", snd_name)
			self.st.signals["sound_end"] = false
		end
	end
end

function action_sound:next_point()
	if self.cur_point+1 < self.st.path:count() then
		return self.cur_point+1
	else
		return 0
	end
	
end

function action_sound:deactivate ()
    if self.snd_obj ~= nil and self.snd_obj:playing () == false then
       self.snd_obj:stop ()
       self.snd_obj = nil
    end    
end

function action_sound:set_positions()
	
	if (self:next_point() == 0) then
		self.slide_active = false
		return
	end

	self.current	= self.st.path:point(self.cur_point)
	self.target		= self.st.path:point(self:next_point())
	self.dir		= vector():sub(self.target, self.current):normalize()
end


---------------------------------------------------------------------------------------------------------------------
function add_to_binder( npc, ini, scheme, section, storage )
	printf("DEBUG: add_to_binder: scheme='%s', section='%s'", scheme, section)

	local new_action = action_sound(npc, storage)

	-- Зарегистрировать все actions, в которых должен быть вызван метод reset_scheme при изменении настроек схемы:
	xr_logic.subscribe_action_for_events( npc, storage, new_action )
end

function set_scheme( obj, ini, scheme, section, gulag_name )
	local st = xr_logic.assign_storage_and_bind( obj, ini, scheme, section )
	st.logic = xr_logic.cfg_get_switch_conditions( ini, section, obj )

	st.sound_names = {}

	if ini:line_exist( section, "snd" ) then
		table_include( st.sound_names, parse_names( ini:r_string( section, "snd" ) ) )
	end

	if ini:line_exist( section, "type" ) then
		local t = parse_names( ini:r_string( section, "type" ) )

		for i, v in pairs(t) do
			table_include( st.sound_names, sound_types[v] )
		end
	end

	if #st.sound_names == 0 then
		abort( "restrictor '%s': no sounds specified in section '%s'", obj:name(), section )
	end

	st.delay   = utils.cfg_get_number( ini, section, "delay",    obj, false, 0 )
	st.idle    = utils.cfg_get_number( ini, section, "idle",     obj, false, 0 ) * 1000 -- секунды->мс
	st.rnd     = utils.cfg_get_number( ini, section, "rnd",      obj, false, 100 )
	local path = utils.cfg_get_string( ini, section, "position", obj, false, "", nil )

	if path == "random" then
		st.pos_type = pos_random
	elseif path ~= nil then
		st.pos_type = pos_path
		st.path = patrol( path )
	else
		st.pos_type = pos_obj
	end
	
	if ini:line_exist( section, "slide_velocity" ) then
		st.sound_slide		= true
		st.sound_slide_vel	= utils.cfg_get_number(ini, section, "slide_velocity",	obj, false, 3)
		st.sound_slide_once	= utils.cfg_get_bool(ini, section, "slide_sound_once",  obj, false)
	else 
		st.sound_slide		= false
	end
	
	st.play_at_actor = utils.cfg_get_bool (ini, section, "play_at_actor", obj, false)
    if st.play_at_actor ~= nil and st.play_at_actor == true then
       if st.pos_type ~= pos_obj then
          abort ("Can't define play sound at actor and path !!!")
       end
    end               
	
end
