---------------------------------------------------------------------------------------------------------------------
--	Схема озвучки
--	автор:  Диденко Руслан  (Stohe)
--	update: Чугай Александр (Chugai)
----------------------------------------------------------------------------------------------------------------------
key_by_id = {}
group_idle = {}

--function printf()
--end

function get_sound(path, tt, npc)
	if path == nil then return nil end
	if path.exec == nil then
		-- чтение настроек темы
		tt.into_id = path.into_id
		tt.into_max = path.max_ids[npc:id()].into_max
		tt.into_last = nil

		tt.rnd_id = path.rnd_id
		tt.rnd_max = path.max_ids[npc:id()].rnd_max
		tt.rnd_last = nil

		tt.min_snd = path.min_snd
		tt.max_snd = path.max_snd
		tt.rnd_snd = path.rnd_snd
	else
		get_sound(path.types[path.exec(path.types, npc)], tt, npc)
	end
end
-- Формирование ключа персонажа
function get_key(npc)
	local key

	-- формирование ключа
	local overrides = xr_logic.generic_scheme_overrides(npc)
	if overrides and
	   overrides.soundgroup 
	then
		key = overrides.soundgroup
	else
		key = utils.to_str(npc:id())
	end
	
	-- апдейт таблиц :) не менять!
	if xr_sound.key_by_id[npc:id()] ~= key then
		if xr_sound.group_idle[xr_sound.key_by_id[npc:id()]] ~= nil	then
		   xr_sound.group_idle[xr_sound.key_by_id[npc:id()]].num_in_group = xr_sound.group_idle[xr_sound.key_by_id[npc:id()]].num_in_group - 1
		end
		xr_sound.key_by_id[npc:id()] = key
		if xr_sound.group_idle[key] == nil then
			xr_sound.group_idle[key] = {num_in_group = 1}
		else
			xr_sound.group_idle[key].num_in_group = xr_sound.group_idle[key].num_in_group + 1
		end
	end
	return key
end
	
-----------------------------------------------------------------------------------------------------------------------------------
--	Установка и распарсивание тем в файлы.
-----------------------------------------------------------------------------------------------------------------------------------
function set_sound(npc, sound, now, into_timeout)
--	printf("*SND* [%s] try to change SND to [%s]", npc:name(), tostring(sound))

	local npc_id = npc:id()
	if (db.sound[npc_id] == nil or
	   db.sound[npc_id].theme ~= sound) or
	   now == true
	then
--		if db.sound[npc_id] == nil then
--			printf("*SND* change SND [_] to [%s] for [%s]", tostring(sound), npc:name())
--		else
--			printf("*SND* change SND [%s] to [%s] for [%s]", tostring(db.sound[npc_id].theme), tostring(sound), npc:name())
--		end
		-- Туточки надобно распарсить имена тем в их id
		if sound == nil then sound = "" end
		if db.sound[npc_id] == nil then db.sound[npc_id] = {} end
		db.sound[npc_id].theme = sound
		db.sound[npc_id].snd = parse_names(sound)
		if db.sound[npc_id].last_snd == nil then
			db.sound[npc_id].last_snd = {}
		else	
		
			local snd_table = {}
			local t = 0		
			for k,v in pairs(db.sound[npc_id].snd) do
				snd_table[t] = {}
				get_sound(sound_theme.theme[v], snd_table[t], npc)
				t = t + 1
			end	
			for k,v in pairs(snd_table) do
				if v.into_id then db.sound[npc_id].last_snd[v.into_id] = nil end
				if v.rnd_id then db.sound[npc_id].last_snd[v.rnd_id] = nil end
			end	
			
			
		end
		-- Устанавливаем входную паузу
		local key = get_key(npc)
		xr_sound.group_idle[key].begin = time_global()
		if into_timeout then
			xr_sound.group_idle[key].idle = into_timeout
		else
			xr_sound.group_idle[key].idle = 0
		end
		
		if now == true then
			stop_play_sound(npc)
		end
	end
end

function set_sound_play(npc, sound, timeout)
	printf("*SND* play SND to [%s] for [%s]", utils.to_str(sound), npc:name())
	local npc_id = npc:id()
	if db.sound[npc_id] == nil then db.sound[npc_id] = {} end
	if db.sound[npc_id].last_snd == nil then
		db.sound[npc_id].last_snd = {}
	end
	stop_play_sound(npc)
	this.play_sound(npc, parse_names(sound), timeout)
end

function update(npc)
	if npc:active_sound_count() ~= 0 then return end
	local key = get_key(npc)
	local npc_id = npc:id()
	
	--' Если задана тема, то нужно играть ее.
	--' Если не задана, то нужно играть idle, при условии что у нас нет врагов и денжеров.
	if db.sound[npc_id] ~= nil and db.sound[npc_id].snd == nil then
		return 
	end	
	
	local group_table = xr_sound.group_idle[key]		
	if group_table == nil then
		return
	end
	
	if group_table.busy == true then
		if group_table.last_npc ~= npc_id then
			return
		end
		if npc:active_sound_count() == 0 then
			group_table.busy = false
		end
	end

	if group_table.num_in_group > 1 and
	   group_table.last_npc == npc_id then
		return
	end

	if table.getn(db.sound[npc_id].snd) == 0 then
		return
	end
	
--	printf("EE: group = %s begin = %s idle = %s", tostring(key), tostring(group_table.begin), tostring(group_table.idle))
	if group_table.begin == nil or
	   time_global() - group_table.begin >= group_table.idle
	then
		this.play_sound(npc, db.sound[npc_id].snd)
		if group_table.idle == nil then
			group_table.idle = 0
		end
		group_table.busy = true
		group_table.begin = time_global()
		group_table.last_npc = npc_id
	end
end


function play_sound(npc, themes, timeout)
	-- нужно составить список тем
	local snd_table = {}
	local t = 0		
	for k,v in pairs(themes) do
		snd_table[t] = {}
		if sound_theme.theme[v] ~= nil then
			snd_table[t].theme = v
			get_sound(sound_theme.theme[v], snd_table[t], npc)
		else
			abort("ERROR: ILLEGAL PLAY SOUND!!! %s for %s", v, npc:name())
		end
		t = t + 1
	end	
	--printf("*")
	--print_table(snd_table)
	if t == 0 then return end
	-- из списка тем выбираем одну.	
	local snd = snd_table[math.random(0, t-1)]
	if snd ~= nil then
		--printf("!")
		--print_table(snd)
		if snd.min_snd == nil then return end
		local npc_id = npc:id()
		local group_table = xr_sound.group_idle[get_key(npc)]
		group_table.idle = math.random(snd.min_snd, snd.max_snd)*1000
		if group_table.last_snd	== nil then
			group_table.last_snd = {}
		end
		-- необходимо ли нам играть into или rnd звуки
		if snd.into_max ~= nil and
			snd.into_max > 0
		then
			if db.sound[npc_id].last_snd[snd.into_id] == snd.into_max - 1 then
				if snd.into_cycled == true then
					db.sound[npc_id].last_snd[snd.into_id] = nil 
				else
					return
				end
			end
			
			-- играем входные
			if db.sound[npc_id].last_snd[snd.into_id] == nil then db.sound[npc_id].last_snd[snd.into_id] = -1 end
			
			--printf("*SND* play seq [%s] for [%s]", db.sound[npc_id].last_snd[snd.into_id]+1, npc:name())
			process_tutor_on_sound(snd.theme)
			npc:play_sound(snd.into_id, 1, 0, 1, 0, db.sound[npc_id].last_snd[snd.into_id]+1)
			db.sound[npc_id].last_snd[snd.into_id] = db.sound[npc_id].last_snd[snd.into_id] + 1
			--printf("*SND* play seq [%s] for [%s]", db.sound[npc_id].last_snd[snd.into_id], npc:name())
			return
		end		
		if snd.rnd_max ~= nil and
			snd.rnd_max > 0
		then
			-- играем рандомные
			local s = 0
			if snd.rnd_max == 1 then
				s = 0
			else
				-- Если прошлый раз проигрывался такой же набор тем
				-- то учитывать последний звук для группы.
--				if db.sound[npc_id].last_snd[snd.rnd_id] ~= nil then
				if group_table.last_snd[snd.rnd_id] ~= nil then
					s = math.random(0, snd.rnd_max-2)
					if s >= group_table.last_snd[snd.rnd_id] then s = s + 1 end
				else
					s = math.random(0, snd.rnd_max-1)					
				end	
			end			

			if timeout == nil then
				timeout = 0
			end							
			--printf("*SND* play rnd [%s] for [%s]", s, npc:name())
			process_tutor_on_sound(snd.theme)
			npc:play_sound(snd.rnd_id, timeout+1, timeout, 1, 0, s)
			--db.sound[npc_id].last_snd[snd.rnd_id] = s
			group_table.last_snd[snd.rnd_id] = s
		end		
	end			
end

function get_last_IDS(npc, theme)
	local last_table = db.sound[npc:id()].last_snd
	local snd_table = {}
	if sound_theme.theme[theme] ~= nil then
		get_sound(sound_theme.theme[theme], snd_table, npc)
	end	
	printf("LAST INTO ID for [%s] = [%s], max [%s]", theme, last_table[snd_table.into_id], snd_table.into_max)
	return last_table[snd_table.into_id], snd_table.into_max
end


function load_sound(npc)
	sound_theme.load_sound(npc)
end

function process_tutor_on_sound(theme)
end


--' Actor sound player
local actor_sound = {}
function set_actor_sound(sound)
	printf("*ACTOR SND* try to change SND to [%s]", tostring(sound))
	if actor_sound.theme ~= sound then
		--' Туточки надобно распарсить имена тем в их id
		if sound == nil then sound = "" end		
		actor_sound.theme = sound
		actor_sound.begin = nil
		
		this.set_actor_sound_factor(1)
	end
end

function set_actor_sound_factor(factor)
	local theme = sound_theme.actor_theme[actor_sound.theme]
	if theme ~= nil then
		actor_sound.min_snd = theme.min_snd * factor
		actor_sound.max_snd = theme.max_snd * factor
	end
end

function update_actor()
	local theme = sound_theme.actor_theme[actor_sound.theme]
	if theme == nil then return end
	
	if table.getn(theme.sounds) == 0 then
		return
	end

	if actor_sound.begin == nil or
	   time_global() - actor_sound.begin >= actor_sound.idle
	then
		actor_sound.begin = time_global()
		
		--' Тут надо отыграть звук
		local sound = theme.sounds[math.random(table.getn(theme.sounds))]
		if sound ~= nil then
			sound:play(db.actor, 0, sound_object.s2d)
		end
		actor_sound.idle = math.random(actor_sound.min_snd, actor_sound.max_snd)
	end
end




--' Таблица для хранения созданных саунд обжектов.
sound_object_by_theme = {}
--' type = [random|seq|looped]
function get_sound_object(theme, t_type)
	if sound_theme.ph_snd_themes[theme] == nil then
		abort("ph_snd_themes for theme %s", tostring(theme))
		return
	end

	if sound_object_by_theme[theme] == nil then
		sound_object_by_theme[theme] = {}
	end

	if t_type == nil then
		t_type = "random"
	end

	--' Выбор следующего айдишника
	local play_id = -1
	local table_size = table.getn(sound_theme.ph_snd_themes[theme])
	if sound_object_by_theme[theme].last_id == nil then
		if t_type == "random" then
			if table_size >= 2 then
				play_id = math.random(1, table_size)
			else
				play_id = 1
			end
		else
			play_id = 1
		end
	else
		if t_type == "random" then
			if table_size >= 2 then
				play_id = math.random(1, table_size - 1)
				if play_id >= sound_object_by_theme[theme].last_id then play_id = play_id + 1 end
			else
				play_id = 1
			end
		else
			if sound_object_by_theme[theme].last_id < table_size then
				play_id = sound_object_by_theme[theme].last_id + 1
			else
				if t_type == "looped" then
					play_id = 1
				end
			end
		end		
	end

	printf("SOUND_OBJECT: selected id [%s] for theme [%s], type [%s], size [%s]", tostring(play_id), tostring(theme), tostring(type), table_size)

	if play_id == -1 then
		return
	end
	--' Проверяем создан ли у нас соответствующий саунд обжект или его надо создать
	if sound_object_by_theme[theme][play_id] == nil then
		if type(sound_theme.ph_snd_themes[theme][play_id]) == "table" then
			sound_object_by_theme[theme][play_id.."_r"] = get_safe_sound_object(sound_theme.ph_snd_themes[theme][play_id][1].."_r")
			sound_object_by_theme[theme][play_id.."_l"] = get_safe_sound_object(sound_theme.ph_snd_themes[theme][play_id][1].."_l")
		else
			sound_object_by_theme[theme][play_id] = get_safe_sound_object(sound_theme.ph_snd_themes[theme][play_id])
		end
	end

	sound_object_by_theme[theme].last_id = play_id

	--' Возвращаем саунд обжект
	if type(sound_theme.ph_snd_themes[theme][play_id]) == "table" then
		return sound_object_by_theme[theme][play_id.."_r"], sound_object_by_theme[theme][play_id.."_l"]
	else
		return sound_object_by_theme[theme][play_id]
	end
end

local sound_object_by_path = {}
--' Обертка вокруг функции, возвращающий звуковой объект.
function get_safe_sound_object(path)
	if sound_object_by_path[path] == nil then
		sound_object_by_path[path] = sound_object(path)
	end
	return sound_object_by_path[path]
end

function stop_all_sound_object()
	for k,v in pairs(sound_object_by_path) do
		if v:playing() then
			v:stop()
		end
	end
end
function clear_all_sound_object()
	sound_object_by_theme = {}
end
