-- nv080209 - adjustments per Russian forum discussion
local ammo = {}
local inited = false
local repack = false

-- nv090719 - for mods without bardak's debug routine
local function dbglog(fmt,...)
	local msg = string.format(fmt, ...)
	local msg_no_ws = string.gsub(msg, "%s", "_")
	get_console():execute("dbg:_" .. msg_no_ws)
end

--------
-- инициализация переменных, выполняется единожды
--------
function init()
	local i, result, section, value
	-- отсюда возьмём размеры полных пачек
	local sys = system_ini()
	-- список патронов возьмём из "death_generic.ltx"
	local ini = ini_file("misc\\death_generic.ltx")
	local n = ini:line_count("ammo_sections")
	for i=0,n-1 do
		result, section, value = ini:r_line("ammo_sections",i,"","")
		ammo[section] = {}
		ammo[section].repack = false
		ammo[section].box = sys:r_u32(section, "box_size")
	end
	repack = false
	inited = true
end

--------
-- вызывается при добавлении в инвентарь ГГ любых патрон
--  obj - game_object добавляемой пачки
-- здесь будем только ставить флажки о необходимости проверки,
-- саму проверку и перепаковку сделаем в апдейте актёра,
-- если перепаковку делать прям здесь, то будет глюк при загрузки и
-- при взятии из нычки кучи патрон (взять всё)
--------
function on_take(obj)
	if not inited then
		init()
	end

	local section = obj:section()
	--dbglog("on_take('%s')", section)

	-- nv080209, 080426 prevent CTD if ammo section missing
	if section ~= nil and ammo[section] ~= nil then
		if ammo[section].repack == false then
			if get_ammo_size(obj) < ammo[section].box then
				ammo[section].repack = true
				repack = true
			end
		end
	else
		-- dbglog("Dunin_ammo_pack: No ammo section for %s",obj:name())
	end
	return repack
end

--------
-- вызывается из апдейта актёра
-- проверяет наличие флажков и вызывает процедуру переупаковки
--------
function on_update()
	if repack then
		local section, data
		for section, data in pairs(ammo) do
			if data.repack then
				repack_ammo(section, data.box)
				data.repack = false
			end
		end
		repack = false
	end
end

--------
-- переупаковка патронов заданного типа
--  section - строка, имя секции (тип патрон)
--  box_size - колличество патрон в полной пачке
-- сначало составляем список неполных пачек, затем
-- удаляем их и создаём нужное колличество полных
--------
function repack_ammo(section, box_size)
	--dbglog("repack_ammo('%s')", section)
	local s, t = enum_ammo(section, box_size)
	if (s > 0) and (table.getn(t) > 1) then
		--dbglog("repacking(magazins=%d, bullets=%d)", table.getn(t), s)
		local i, id
		local sim = alife()
		local pos = db.actor:position()
		local lvid = db.actor:level_vertex_id()
		local gvid = db.actor:game_vertex_id()
		local pid = db.actor:id()

		for i, id in pairs(t) do
			sim:release(sim:object(id), true)
		end

		while s >= box_size do
			sim:create_ammo(section, pos, lvid, gvid, pid, box_size)
			s = s - box_size
		end

		if s > 0 then
			sim:create_ammo(section, pos, lvid, gvid, pid, s)
		end
	end
end

--------
-- пробегаемся по инветарю ГГ и собираем инфу о неполных пачках
--  section - строка, имя секции (тип патрон)
--  box_size - колличество патрон в полной пачке
-- возвращает сумарное колличество патрон в неполных пачках и массив id-шников этих пачек
--------
function enum_ammo(section, box_size)
	local i, obj, size
	local s = 0
	local t = {}
	for i=0, db.actor:object_count()-1 do
		obj = db.actor:object(i)
		if obj:section() == section then
			size = get_ammo_size(obj)
			-- if size < box_size then
			if size ~= box_size then
				table.insert(t, obj:id())
				s = s + size
			end
		end
	end
	return s, t
end

--------
-- возвращает колличество патрон в пачке
-- вроде подходящих функций нет, пришлось делать через net_packet
--------
function get_ammo_size(obj)
	local se_obj = alife():object(obj:id())
	local packet = net_packet()
	cse_alife_item_ammo.STATE_Write(se_obj, packet)
	--packet:r_advance(18)
	--packet:r_stringZ()
	--packet:r_advance(8)
	--packet:r_stringZ()
	--packet:r_advance(5)
	packet:r_seek(packet:w_tell() - 2)
	return packet:r_u16()
end
