---------------------------------------
--	itms_manager
--
-- by Alundaio
---------------------------------
--[[
Copyright (C) 2012 Alundaio
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License-]]
--]]
local ini = ini_file("plugins\\itms_manager.ltx")
	--Backpack stash mod
	local BackPackStashEnable = alun_utils.read_from_ini(ini,"backpack_stash","enable","bool",true)
	local BackPackStashAllowInBase = BackPackStashEnable and alun_utils.read_from_ini(ini,"backpack_stash","allow_in_base","bool",false)
	local BackPackStashSpot = BackPackStashEnable and alun_utils.read_from_ini(ini,"backpack_stash","map_spot","string","treasure")
	local BackPackStashEnableTip = BackPackStashEnable and alun_utils.read_from_ini(ini,"backpack_stash","enable_news_tip","bool",true)
	local BackPackStashEnableUi = BackPackStashEnable and alun_utils.read_from_ini(ini,"backpack_stash","enable_ui","bool",true)

	-- Sleep bag mod
	local SleepBagEnable = alun_utils.read_from_ini(ini,"sleeping_bag","enable","bool",true)
	local SleepBagEnableDangerous = SleepBagEnable and alun_utils.read_from_ini(ini,"sleeping_bag","dangerous_sleep","bool",true)
	local SleepBagRadius = SleepBagEnable and alun_utils.read_from_ini(ini,"sleeping_bag","unsafe_radius","float",5000)
	local SleepBagPlaceable = SleepBagEnable and alun_utils.read_from_ini(ini,"sleeping_bag","use_placeable","bool",true)
	local SleepBagGameStart = SleepBagEnable and alun_utils.read_from_ini(ini,"sleeping_bag","have_at_start","bool",true)
	local SleepBagSections = SleepBagEnable and alun_utils.collect_section(ini,"sleeping_bag_sections",true)
	local SleepBagPlaceableSections = SleepBagEnable and alun_utils.collect_section(ini,"sleeping_bag_ph_sections",true)

	-- Actor backpack mod
	local ActorBackPackEnable = alun_utils.read_from_ini(ini,"actor_backpack","enable","bool",true)
	local ActorBackPackSpot = ActorBackPackEnable and alun_utils.read_from_ini(ini,"actor_backpack","map_spot","string","treasure")
	local ActorBackPackSlot = ActorBackPackEnable and alun_utils.read_from_ini(ini,"actor_backpack","quick_slot","string","slot_3")
	local ActorBackPackKeep = ActorBackPackEnable and alun_utils.collect_section(ini,"actor_backpack_keep_items",true)
	local ActorBackPackForced = ActorBackPackEnable and alun_utils.read_from_ini(ini,"actor_backpack","actor_backpack_always_have","bool",true)

	-- Repair mod
	local RepairModEnable = alun_utils.read_from_ini(ini,"repair_mod","enable","bool",true)
	local RepairTools = RepairModEnable and alun_utils.collect_section(ini,"repair_mod_tools",true)

	-- Cooking mod
	local CookingModEnable = alun_utils.read_from_ini(ini,"cooking_mod","enable","bool",true)
	local CookingTools = CookingModEnable and alun_utils.collect_section(ini,"cooking_mod_tools",true)


	-- Loot Mutant mod
	local MutantLootEnable = alun_utils.read_from_ini(ini,"mutant_loot_mod","enable","bool",true)
	local MutantLootEnableUI = alun_utils.read_from_ini(ini,"mutant_loot_mod","enable_ui","bool",true)
	local MutantLootDecayTime = alun_utils.read_from_ini(ini,"mutant_loot_mod","decay_time","float",7200)

	-- Flashlight mod
	local FlashlightModEnable = alun_utils.read_from_ini(ini,"flashlight_mod","enable","bool",true)
	local FlashlightSections = FlashlightModEnable and alun_utils.collect_section(ini,"flashlight_sections",true)

-- Static Message
ShowMessage = nil
ShowMessageInit = nil
ShowMessageTime = nil


function on_game_start()
	callback_register("on_game_load",on_game_load)
	callback_register("actor_on_update",actor_on_update)
	callback_register("actor_on_item_drop",actor_on_item_drop)
	callback_register("monster_on_actor_use_callback",monster_on_actor_use_callback)
	callback_register("actor_on_item_use",actor_on_item_use)
	callback_register("actor_on_item_take_from_box",actor_on_item_take_from_box)
	callback_register("physic_object_on_use_callback",physic_object_on_use_callback)
	callback_register("squad_assign_new_target",squad_assign_new_target)
	--callback_register("npc_on_item_take_from_box",npc_on_item_take_from_box)
end

function on_game_load()

	if (ActorBackPackEnable and ActorBackPackForced) then
		local actor_itm_backpack_id= xr_logic.pstor_retrieve(db.actor,"actor_itm_backpack_id",nil)
		local actor_inv_backpack_id = xr_logic.pstor_retrieve(db.actor,"actor_inv_backpack_id",nil)
		if (not actor_itm_backpack_id and not actor_inv_backpack_id) then
			get_console():execute(ActorBackPackSlot.." itm_actor_backpack")
			local se_obj = alife():create("itm_actor_backpack",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
			xr_logic.pstor_store(db.actor,"actor_itm_backpack_id",se_obj.id)
		end
	end

	if (SleepBagEnable and SleepBagGameStart) then
		local sleepbag_id = xr_logic.pstor_retrieve(db.actor,"itm_sleepbag_id",nil)
		if (not sleepbag_id) then
			local se_obj = alife():create("itm_sleepbag",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),0)
			xr_logic.pstor_store(db.actor,"itm_sleepbag_id",se_obj.id)
		end
	end
end

local torch_delay
-- bind_stalker update
local actor_fill_backpack
function actor_on_update()
	check_actor_backpack()
	if (ShowMessage and ShowMessageInit) then
		local hud = get_hud()
		local custom_static = hud:GetCustomStatic("can_use_weapon_now")
		if custom_static ~= nil and game.get_game_time():diffSec(ShowMessageInit) > ShowMessageTime then
			hud:RemoveCustomStatic("can_use_weapon_now")
			ShowMessage = nil
			ShowMessageTime = nil
			ShowMessageInit = nil
		end
	end


	if (FlashlightModEnable) then
		local obj = db.actor:active_detector()
		local torch = db.actor:object("device_torch")
		if (obj and FlashlightSections[obj:section()]) then
			if (has_alife_info("enable_device_torch")) then
				db.actor:disable_info_portion("enable_device_torch")
				alife():create("device_torch_dummy",db.actor:position(),0,0,0)
				show_message("Налобный фонарик отключен от УЗ",25)
			end

			if not (torch) then
				alife():create("device_torch",db.actor:position(),0,0,0)
			end

			if (torch and not torch:torch_enabled()) then
				if not (torch_delay) then
					torch_delay = time_global() + 1000
				end

				if (time_global() > torch_delay) then
					torch:enable_torch(true)
				end
			end
		else
			if (torch and not has_alife_info("enable_device_torch")) then
				if (torch:torch_enabled()) then
					torch:enable_torch(false)
					torch_delay = nil
				end
			end
		end
	end
end

-- bind_stalker on_trade
function actor_on_trade(obj,sell_bye,money)

end

-- bind_stalker on_item_take
function actor_item_take(obj)

end

-- bind_stalker on_item_drop
function actor_on_item_drop(obj)
	if not (obj) then
		return
	end

	if (ActorBackPackEnable and ActorBackPackForced and obj:section() == "itm_actor_backpack") then
		local se_itm = alife():create("itm_actor_backpack",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),db.actor:id())

		if not (se_itm) then
			return
		end

		xr_logic.pstor_store(db.actor,"actor_itm_backpack_id",se_itm.id)
		alife():release( alife():object(obj:id()) )
	end

end

function monster_on_actor_use_callback(obj,who)
	if not (MutantLootEnable) then
		return
	end

	local looted = xr_logic.pstor_retrieve(obj,"looted",nil)
	if (looted) then
		return
	end

	xr_logic.pstor_store(obj,"looted",true)
	xr_corpse_detection.set_valuable_loot(obj:id(),false)

	local st = db.storage[obj:id()]
	if (st and st.death_time and game.get_game_time():diffSec(st.death_time) > MutantLootDecayTime) then
		show_message("Тело слишком повреждено",25)
	else
		if (MutantLootEnableUI and ui_mutant_loot) then
			ui_mutant_loot.loot_ui(get_hud(),obj:id(),obj:section(),obj:clsid())
		else
			loot_mutant(se_obj,obj:clsid())
		end
	end
end


-- bind_stalker on_item_use
function actor_on_item_use(obj)

	-- Backpack
	if (BackPackStashEnable and obj:section() == "itm_backpack") then
		local in_base
		local zone
		local t = {"zat_a2_sr_no_assault","jup_a6_sr_no_assault","jup_b41_sr_no_assault"}
		for i=1,#t do
			zone = db.zone_by_name[t[i]]
			if (zone and zone:inside(db.actor:position())) then
				in_base = true
				break
			end
		end

		if (BackPackStashAllowInBase ~= true and in_base) then
			show_message("Not safe to place it here",25)
			alife():create("itm_backpack",db.actor:position(),0,0,0)
			return
		else
			local se_obj = alife():create("inv_backpack",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id())

			local level_name = level.name()

			if not (BackPackStashEnableUi) then
				local count = xr_logic.pstor_retrieve(db.actor, level_name.."bpk_count", 0)
				xr_logic.pstor_store(db.actor, level_name.."bpk_count", count+1)
				level.map_add_object_spot_ser(se_obj.id, BackPackStashSpot, level_name.." stash "..count+1)
			else
				local hud = get_hud()
				hud:HideActorMenu()
				local ui = ui_itm_backpack and ui_itm_backpack.backpack_ui(hud,se_obj.id,BackPackStashSpot)
				if (ui) then
					ui:ShowDialog(true)
				end
			end

			if (BackPackStashEnableTip) then
				show_message("Stash created",25)
			end
		end
		return
 	end

	-- Sleeping bag
	if (SleepBagEnable and SleepBagSections[obj:section()]) then
		local sec = obj:section()
		if (SleepBagPlaceable) then
			local ph_sec = alun_utils.read_from_ini(nil,sec,"placeable_section","string",nil)
			local se_obj = alife():create(ph_sec or "ph_sleepbag",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id())
			se_obj.sleepbag_section = sec
		else
			local se_obj = alife():create(sec,db.actor:position(),0,0,0)
			local hud = get_hud()
			hud:HideActorMenu()
			local ui = ui_sleep_dialog.sleep_bag(se_obj,sec)
		end
		return
	end

	-- Actor backpack
	if (ActorBackPackEnable and obj:section() == "itm_actor_backpack") then
		local id = xr_logic.pstor_retrieve(db.actor,"actor_inv_backpack_id",nil)
		if (id) then
			show_message("Я уже оставил где-то свой рюкзак",30)
			alife():create("itm_actor_backpack",db.actor:position(),0,0,0)
			return
		end

		local se_obj = alife():create("inv_actor_backpack",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id())

		level.map_add_object_spot_ser(se_obj.id, ActorBackPackSpot, db.actor:character_name().."'s backpack")

		xr_logic.pstor_store(db.actor,"actor_inv_backpack_id",se_obj.id)
	end

	-- Repair mod
	if (RepairModEnable and RepairTools[obj:section()]) then
		local hud = get_hud()
		--hud:HideActorMenu()
		local ui = ui_itm_repair and ui_itm_repair.repair_ui(hud,obj:section())
		if (ui) then
			ui:ShowDialog(true)
			ui:FillList()
		end
	end

	-- Cooking mod
	if (CookingModEnable and CookingTools[obj:section()]) then
		local hud = get_hud()
		--hud:HideActorMenu()
		local ui = ui_itm_cooking and ui_itm_cooking.cooking_ui(hud,obj:section())
		if (ui) then
			ui:ShowDialog(true)
			ui:FillList()
		end
	end


	-- Dummy Torch for Flashlight
	if (FlashlightModEnable and obj:section() == "device_torch_dummy") then
		local torch = db.actor:object("device_torch")
		if not (has_alife_info("enable_device_torch")) then
			give_info("enable_device_torch")
			if not (torch) then
				alife():create("device_torch",db.actor:position(),0,0,0)
			end
			show_message("Налобный фонарик подключен",25)
		end
	end
end

function check_actor_backpack()
	if (db.actor:has_info("actor_filled_backpack"))then
		return
	end

	local id = xr_logic.pstor_retrieve(db.actor,"actor_inv_backpack_id",nil)

	if not (id) then
		return
	end

	local se_obj = alife():object(id)
	local obj = db.storage[se_obj.id] and db.storage[se_obj.id].object or level.object_by_id(id)

	if not (obj) then
		return
	end

	local function itr_inv(temp,item)
		local id = item and item:section() ~= "itm_actor_backpack" and ActorBackPackKeep[item:section()] == nil and item:id()
		if (id and not is_ammo_for_wpn(item:section())) then
			local itm_slot
			local equipped
			for i=1,12 do
				if (i ~= 4) then
					itm_slot = db.actor:item_in_slot(i)
					if (itm_slot and itm_slot:id() == id) then
						equipped = true
						break
					end
				end
			end

			if (not equipped) then
				db.actor:transfer_item(item,obj)
			end
			equipped = nil
		end
	end

	db.actor:iterate_inventory(itr_inv)

	db.actor:give_info_portion("actor_filled_backpack")
end

-- bind_stalker take_item_from_iventory_box
function actor_on_item_take_from_box(box,obj)
	if not (box) then
		return
	end

	if not (obj) then
		return
	end

	-- Backpack section
	if (BackPackStashEnable and box:section() == "inv_backpack") then
		if (box:is_inv_box_empty()) then
			local hud = get_hud()
			hud:HideActorMenu()

			level.map_remove_object_spot(box:id(), BackPackStashSpot)
			alife():create("itm_backpack",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),db.actor:id())

			alife():release( alife():object(box:id()) ,true)
		end
	end

	-- Actor backpack section
	if (ActorBackPackEnable and box:section() == "inv_actor_backpack") then
		if (box:is_inv_box_empty()) then
			local hud = get_hud()
			hud:HideActorMenu()

			level.map_remove_object_spot(box:id(), BackPackActorSpot)

			alife():release( alife():object(box:id()) ,true)

			alife():create("itm_actor_backpack",db.actor:position(),db.actor:level_vertex_id(),db.actor:game_vertex_id(),db.actor:id())
			
			xr_logic.pstor_store(db.actor,"actor_inv_backpack_id",nil)

			db.actor:disable_info_portion("actor_filled_backpack")
		end
	end
end

function npc_on_item_take_from_box(npc,box,item)

end

-- bind_physic_object use_callback
function physic_object_on_use_callback(obj,who)
	if (SleepBagEnable and SleepBagPlaceableSections[obj:section()]) then
		local hud = get_hud()
		hud:HideActorMenu()
		local se_obj = alife():object(obj:id())
		local ui = ui_sleep_dialog.sleep_bag(obj:id(),se_obj.sleepbag_section)
	end
end

sleep_actor_safe = nil
function squad_assign_new_target(squad)
	if not (SleepBagEnableDangerous) then
		return
	end

	if not (sleep_actor_safe) then
		return
	end

	if not (has_alife_info("actor_is_sleeping")) then
		return
	end

	if not (game_relations.get_squad_goodwill_to_actor_by_id(squad.id) == "enemy") then
		return
	end

	local dist = db.actor:position():distance_to_sqr(squad.position)
	if (dist < SleepBagRadius) then
		--alun_utils.printf("actor is target")
		return 0
	end
end

function is_ammo_for_wpn(sec) --Adjusted to allow 3 types of ammo for weapon to stay in inventory...Yasti
	local ammos, wpn, data
	local sim = alife()
	for i=2,3 do
		wpn = db.actor:item_in_slot(i)
		if (wpn) then

			ammos = alun_utils.parse_list(system_ini(),wpn:section(),"ammo_class")

			se_wpn = sim:object(wpn:id())
			data = stpk_utils.get_weapon_data(se_wpn)

			if (sec == ammos[data.ammo_type+1]) then
				return true
			end
			--Adjusted Yasti
			if (sec == ammos[data.ammo_type+2]) then
				return true
			end
			if (sec == ammos[data.ammo_type+3]) then
				return true
			end
			--End Yasti
		end
	end
	return false
end

local clsid_to_section = {
		[clsid.bloodsucker_s] 	= "bloodsucker",
		[clsid.boar_s] 			= "boar",
		[clsid.burer_s] 		= "burer",
		[clsid.chimera_s]		= "chimera",
		[clsid.controller_s]	= "controller",
		[clsid.dog_s]			= "dog",
		[clsid.flesh_s]			= "flesh",
		[clsid.gigant_s]		= "gigant",
		[clsid.poltergeist_s]	= "poltergeist",
		[clsid.psy_dog_s]		= "psy_dog",
		[clsid.pseudodog_s]		= "pseudodog",
		[clsid.snork_s]			= "snork",
		[clsid.tushkano_s]		= "tushkano",
		[clsid.cat_s]			= "cat",
		[clsid.fracture_s]		= "fracture",
		[clsid.zombie_s]		= "zombie",
		[clsid.crow]			= "crow"
}

function loot_mutant(obj,clsid,t,npc)
	local clsid = clsid or obj and obj:clsid()
	if not (clsid) then
		return
	end

	--alun_utils.printf("loot_mutant: collecting section=%s",clsid_to_section[clsid])
	local loot_table = alun_utils.collect_section(ini,clsid_to_section[clsid])

	local loot,sec
	for i=1,#loot_table do
		loot = alun_utils.str_explode(loot_table[i],",")
		if (loot and loot[1] and loot[2]) then
			if not (loot[3]) then
				loot[3] = 1
			end

			loot[2] = tonumber(loot[2])
			for i=1,loot[2] do
				if (math.random() <= tonumber(loot[3])) then
					--alun_utils.printf("loot_mutant: section=%s",loot[1])
					local se_obj = alife():create(loot[1],npc and npc:position() or db.actor:position(),0,0,npc and npc:id() or 0)
					if (t) then
						local item_section = loot[1]
						if not (t[item_section]) then
							t[item_section] = {}
						end
						t[item_section].count = t[item_section].count and t[item_section].count + 1 or 1
						t[item_section][t[item_section].count] = se_obj.id
						--alun_utils.printf("loot_mutant")
					end
				end
			end
		end
	end
end

function show_message(msg,time)
	local hud = get_hud()
	hud:AddCustomStatic("can_use_weapon_now", true)
	hud:GetCustomStatic("can_use_weapon_now"):wnd():TextControl():SetTextST(msg)
	ShowMessage = true
	ShowMessageInit = game.get_game_time()
	ShowMessageTime = time
end
