--'*************************************************************************************
--' Функторы тайтла и описания квеста (должны возвращать строку)
--'*************************************************************************************
---
-- HELPERS
-----------------------------------------------------------
local function under_faction_control_target_id(task_id)
	local smart_id = db.actor and alun_utils.load_var(db.actor,task_id.."_id")
	if not (smart_id) then
		printf("task_functor.under_faction_control_target_id is nil")
		return
	end
	local sim = alife()
	local smart = smart_id and sim:object(smart_id)
	if not (smart) then
		printf("task_functor.under_faction_control_target_id smart by id is nil")
		return
	end

	local target_id = alun_utils.load_var(db.actor,task_id.."_target_id")
	local se_target = target_id and sim:object(target_id)

	if (se_target and smart.position:distance_to_sqr(se_target.position) > 2500) then
		return target_id
	end

	return smart_id
end

function get_squad_id_by_task_var(var_name,no_check_online)
	local npc_id = db.actor and alun_utils.load_var(db.actor,var_name)
	if not (npc_id) then
		return
	end

	-- by default npc's id is returned instead if game_object is online
	if not (no_check_online) then
		local npc = npc_id and db.storage[npc_id] and db.storage[npc_id].object
		if (npc) then
			return npc_id
		end
	end

	local sim = alife()
	local se_npc = sim:object(npc_id)
	if not (se_npc) then
		return
	end

	local squad = se_npc.group_id and se_npc.group_id ~= 65535 and sim:object(se_npc.group_id)
	if not (squad) then
		if (no_check_online) then
			return
		end
		return npc_id
	end

	return squad.id
end
---------------------------------------------------------
-- TASK FUNCTORS
---------------------------------------------------------
function general_bounty_task(task_id,field,p,task)
	if (field == "target") then
		if (task) then
			if (task.stage == 1) then
				return task.task_giver_id or nil
			end

			return axr_task_manager.bounties_by_id[task_id] or nil
		end
	end
end

function general_fetch_task(task_id,field,p,task)
	if not (db.actor) then
		return
	end
	if (field == "title") then
		local fetch = alun_utils.get_inv_name(alun_utils.load_var(db.actor,task_id.."_fetch",""))
		local count = alun_utils.load_var(db.actor,task_id.."_fetch_count") or 1
		if (count > 1) then
			return strformat((game.translate_string(p) or ""),fetch .. " x" .. tostring(count))
		end
		return strformat(game.translate_string(p) or "",fetch)
	elseif (field == "descr") then
		if (task.stage == 1) then
			return game.translate_string("st_return_for_reward")
		end
		local fetch = alun_utils.get_inv_name(alun_utils.load_var(db.actor,task_id.."_fetch",""))
		local count = alun_utils.load_var(db.actor,task_id.."_fetch_count") or 1
		if (count > 1) then
			return strformat((game.translate_string(p) or ""),fetch .. " x" .. tostring(count))
		end
		return strformat(game.translate_string(p) or "",fetch)
	elseif (field == "target") then
		if (task.stage == 1) then
			local id = alun_utils.load_var(db.actor,task_id.."_target_id") or task.task_giver_id
			if (id) then
				return id
			end
			local story_id = string.sub(task_id,1,string.find(task_id,"_task")-1)
			local se_obj = get_story_se_object(story_id)
			if (se_obj) then
				return se_obj.id
			end
		end
	end
end

function general_under_faction_control(task_id,field,p,task)
	if (field == "target") then
		if (task and task.stage == 1 and task.task_giver_id) then
			return task.task_giver_id
		end

		return under_faction_control_target_id(task_id)
	end
end

-- Yantar
function yan_ecolog_semenov_task_target(task_id,field,p,task)
	if (task_id == "yan_ecolog_semenov_task_1") then
		local squad = get_story_squad("yan_ecolog_semenov_squad")
		if (db.actor and squad and squad.dist_to_actor and squad.dist_to_actor > 50) then
			return squad.id
		end

		if (task.stage >= 1) then
			return squad.id
		end
	end
end

-- Marsh
function mar_base_stalker_barmen_task_target(task_id,field,p,task)
	if not (db.actor) then
		return
	end

	if (task and task.stage == 1 and task.task_giver_id) then
		return task.task_giver_id
	end

	if (task_id == "mar_base_stalker_barmen_task_1") then
		return under_faction_control_target_id(task_id)
	elseif (task_id == "mar_base_stalker_barmen_task_2") then
		return under_faction_control_target_id(task_id)
	end
end

function mar_base_owl_stalker_trader_task_target(task_id,field,p)
	if (task_id == "mar_base_owl_stalker_trader_task_1") then
		local se_npc = get_story_se_object("esc_2_12_stalker_nimble")
		return se_npc and se_npc.id or nil
	elseif (task_id == "mar_base_owl_stalker_trader_task_2") then
		for id,obj in pairs(db.heli) do
			if (obj and obj.id) then
				return id
			end
		end
	elseif (task_id == "mar_base_owl_stalker_trader_task_3") then
		local squad = get_story_squad("ecolog_companion_task_1")
		if (db.actor and squad and squad.dist_to_actor and squad.dist_to_actor > 50) then
			return squad.id
		end
		local n = db.actor and alun_utils.load_var(db.actor,"task_target_anomaly")
		if (n) then
			local anomaly = db.anomaly_by_name[n]
			if (anomaly and anomaly.object) then
				return anomaly.object:id()
			end
		else
			local smart = SIMBOARD.smarts_by_names["mar_smart_terrain_base"]
			if (smart) then
				return smart.id
			end
		end
	end
end

-- Escape
function esc_m_trader_task_target(task_id,field,p,task)
	if (field == "target") then
		if (task_id == "esc_m_trader_task_1") then
			if (task.stage == 1) then
				return task.task_giver_id
			end

			local smart = SIMBOARD.smarts_by_names["esc_smart_terrain_7_11"]
			local target_id = alun_utils.load_var(db.actor,"esc_m_trader_task_1_target_id")
			local se_target = target_id and alife():object(target_id)

			if (se_target and smart.position:distance_to_sqr(se_target.position) > 2500) then
				return target_id
			end

			return smart and smart.id or nil
		end
	end
end

-- Darkvalley
function val_smart_terrain_7_4_bandit_trader_stalker_task_target(task_id,field,p,task)
	if not (db.actor) then
		return
	end

	if (task_id == "val_smart_terrain_7_4_bandit_trader_stalker_task_3") then
		local squad = get_story_squad("bandit_companion_task_1")
		if (squad and squad.dist_to_actor and squad.dist_to_actor > 50) then
			return squad.id
		end
	end
end

function agr_smart_terrain_1_6_army_trader_stalker_task_target(task_id,field,p,task)
	if not (db.actor) then 
		return 
	end
	
	if (task_id == "agr_smart_terrain_1_6_army_trader_stalker_task_4") then 
		local squad = get_story_squad("army_companion_task_1")
		if (squad and squad.dist_to_actor and squad.dist_to_actor > 50) then 
			return squad.id
		end
	end
end

function mil_smart_terrain_7_7_freedom_leader_stalker_task_target(task_id,field,p,task)
	if not (db.actor) then 
		return 
	end
	
	if (task_id == "mil_smart_terrain_7_7_freedom_leader_stalker_task_6") then 
		local squad = get_story_squad("freedom_companion_task_1")
		if (squad and squad.dist_to_actor and squad.dist_to_actor > 50) then 
			return squad.id
		end
	end
end

function bar_dolg_general_petrenko_stalker_task_target(task_id,field,p,task)
	if not (db.actor) then 
		return 
	end
	
	if (task_id == "bar_dolg_general_petrenko_stalker_task_4") then 
		local squad = get_story_squad("dolg_companion_task_1")
		if (squad and squad.dist_to_actor and squad.dist_to_actor > 50) then 
			return squad.id
		end
	end
end

function cit_killers_merc_trader_stalker_task_target(task_id,field,p,task)
	if not (db.actor) then 
		return 
	end
	
	if (task_id == "cit_killers_merc_trader_stalker_task_3") then 
		local squad = get_story_squad("killer_companion_task_1")
		if (squad and squad.dist_to_actor and squad.dist_to_actor > 50) then 
			return squad.id
		end
	end
end

function esc_2_12_stalker_wolf_task_target(task_id,field,p,task)
	if not (db.actor) then 
		return 
	end
	
	if (task_id == "esc_2_12_stalker_wolf_task_2") then 
		local squad = get_story_squad("stalker_companion_task_1")
		if (squad and squad.dist_to_actor and squad.dist_to_actor > 50) then 
			return squad.id
		end
	end
end

function mar_base_stalker_barmen_task_target(task_id,field,p,task)
	if not (db.actor) then 
		return 
	end
	
	if (task_id == "mar_base_stalker_barmen_task_4") then 
		local squad = get_story_squad("csky_companion_task_1")
		if (squad and squad.dist_to_actor and squad.dist_to_actor > 50) then 
			return squad.id
		end
	end
end

function pri_monolith_monolith_trader_stalker_task_target(task_id,field,p,task)
	if not (db.actor) then 
		return 
	end
	
	if (task_id == "pri_monolith_monolith_trader_stalker_task_7") then 
		local squad = get_story_squad("monolith_companion_task_1")
		if (squad and squad.dist_to_actor and squad.dist_to_actor > 50) then 
			return squad.id
		end
	end
end


function yan_stalker_sakharov_task_target(task_id,field,p)
	if (task_id == "yan_stalker_sakharov_task_2") then
		local squad = get_story_squad("ecolog_companion_task_3")
		if (db.actor and squad and squad.dist_to_actor and squad.dist_to_actor > 50) then
			return squad.id
		end
		local n = db.actor and alun_utils.load_var(db.actor,"task_target_anomaly")
		if (n) then
			local anomaly = db.anomaly_by_name[n]
			if (anomaly and anomaly.object) then
				return anomaly.object:id()
			end
		else
			local smart = SIMBOARD.smarts_by_names["yan_smart_terrain_6_4"]
			if (smart) then
				return smart.id
			end
		end
	end
end

-- soc pripyat


-- Jupiter
function jup_b6_scientist_tech_task_target(task_id,field,p,task)
	if (task_id == "jup_b6_scientist_tech_task_1") then
		local squad = get_story_squad("ecolog_companion_task_2")
		if (db.actor and squad and squad.dist_to_actor and squad.dist_to_actor > 50) then
			return squad.id
		end
		local n = db.actor and alun_utils.load_var(db.actor,"task_target_anomaly")
		if (n) then
			local anomaly = db.anomaly_by_name[n]
			if (anomaly and anomaly.object) then
				return anomaly.object:id()
			end
		else
			local smart = SIMBOARD.smarts_by_names["jup_b41"]
			if (smart) then
				return smart.id
			end
		end
	end
end

-- Zaton
function zat_b7_bandit_boss_sultan_task_target(task_id,field,p)
	if (task_id == "zat_b7_bandit_boss_sultan_task_1") then
		return get_squad_id_by_task_var("zat_b7_bandit_boss_sultan_bounty_target_id") --add to axr_main remove_non_story_squads to ensure squad never removed
	end
end

-- Simulation
function simulation_task_target(task_id,field,p,task)
	if not (db.actor) then
		return
	end

	if (task_id == "simulation_task_7" or task_id == "simulation_task_8" or task_id == "simulation_task_9" or task_id == "simulation_task_10" or task_id == "simulation_task_19" or task_id == "simulation_task_20" or task_id == "simulation_task_31" or task_id == "simulation_task_32" or task_id == "simulation_task_33") then
		local squad = get_story_squad("hostage_companion_task_1")
		if not (squad and squad:clsid() == clsid.online_offline_group_s) then
			return -- quest will auto-fail via section condition
		end

		if (task) then
			if (task.stage == 0) or (squad and squad.dist_to_actor and squad.dist_to_actor > 50) then
				return squad and squad.id
			elseif (task.stage >= 1 or db.actor:has_info("hostage_companion_task_1_hostage_rescued")) then
				local id = task.task_giver_id
				if (id) then
					return id
				end
			end
		end

		return squad.id
	end
end

--[[
==================================================================

==================================================================
--]]

function condlist(id, field, p)
	local cond_string = p

	local parsed_condlist = xr_logic.parse_condlist(nil, "task", "task_condlist", cond_string)
	return xr_logic.pick_section_from_condlist(get_story_object("actor"), nil, parsed_condlist)
end

function zat_b29_adv_title(id, field, p)
	local actor = get_story_object("actor")
	for i = 16, 23 do
		if (has_alife_info(dialogs_zaton.zat_b29_infop_bring_table[i]) and actor:object(dialogs_zaton.zat_b29_af_table[i])) then
			title = "zat_b29_simple_bring_title_"..i
			break
		elseif has_alife_info(dialogs_zaton.zat_b29_infop_bring_table[i]) then
			title = "zat_b29_simple_find_title_"..i
			break
		end
	end

	return title
end

function zat_b29_adv_descr(id, field, p)
	local descr
	local f_af = 0
	local actor = get_story_object("actor")

	for i = 16, 23 do
		if (has_alife_info(dialogs_zaton.zat_b29_infop_bring_table[i]) and actor:object(dialogs_zaton.zat_b29_af_table[i])) then
			f_af = 1
			descr = "zat_b29_simple_bring_text_5"
			if has_alife_info("zat_b29_stalker_rival_1_found_af") and has_alife_info("zat_b29_first_rival_taken_out") and f_af ~= 0 then
				return descr
			elseif has_alife_info("zat_b29_stalker_rival_2_found_af") and has_alife_info("zat_b29_second_rival_taken_out") and f_af ~= 0 then
				return descr
			elseif has_alife_info("zat_b29_linker_take_af_from_rival") then
				descr = "zat_b29_simple_bring_text_4"
			elseif has_alife_info("zat_b29_stalkers_rivals_found_af") then
				descr = "zat_b29_simple_bring_text_3"
			elseif has_alife_info("zat_b29_rivals_search") and has_alife_info("zat_b29_exclusive_conditions") then
				descr = "zat_b29_simple_bring_text_1"
			elseif has_alife_info("zat_b29_rivals_search") then
				descr = "zat_b29_simple_bring_text_2"
			end
			break
		elseif has_alife_info(dialogs_zaton.zat_b29_infop_bring_table[i]) then
			descr = "zat_b29_simple_find_text_5"
			if has_alife_info("zat_b29_stalker_rival_1_found_af") and has_alife_info("zat_b29_first_rival_taken_out") and f_af ~= 0 then
				return descr
			elseif has_alife_info("zat_b29_stalker_rival_2_found_af") and has_alife_info("zat_b29_second_rival_taken_out") and f_af ~= 0 then
				return descr
				elseif has_alife_info("zat_b29_linker_take_af_from_rival") then
					descr = "zat_b29_simple_find_text_4"
				elseif has_alife_info("zat_b29_stalkers_rivals_found_af") then
					descr = "zat_b29_simple_find_text_3"
				elseif has_alife_info("zat_b29_rivals_search") and has_alife_info("zat_b29_exclusive_conditions") then
					descr = "zat_b29_simple_find_text_1"
				elseif has_alife_info("zat_b29_rivals_search") then
					descr = "zat_b29_simple_find_text_2"
				end
			break
		end
	end

	return descr
end

function surge_task_title(id, field, p)
	if(surge_manager.actor_in_cover()) then
		return "hide_from_surge_name_2"
	else
		return "hide_from_surge_name_1"
	end
end

function surge_task_descr(id, field, p)
	return surge_manager.get_task_descr()
end
--'*************************************************************************************
--' Функторы цели квеста (должны возвращать id персонажа)
--'*************************************************************************************

function target_condlist(task_id, field, p)
	local cond_string = p

	local parsed_condlist = xr_logic.parse_condlist(nil, "task", "task_condlist", cond_string)
	local value = xr_logic.pick_section_from_condlist(get_story_object("actor"), nil, parsed_condlist)

	if value == nil then
		return nil
	end

	local target_obj_id = get_story_object_id(value)

	if target_obj_id == nil then
	--	printf("There is no object with story_id %s", value)
	end

	return target_obj_id
end

function zat_b29_adv_target(task_id, field, p)
	local target_obj_id = "zat_a2_stalker_barmen"
	local af = nil
	local actor = get_story_object("actor")


	for i = 16, 23 do
		if (has_alife_info(dialogs_zaton.zat_b29_infop_bring_table[i])
			and actor:object(dialogs_zaton.zat_b29_af_table[i])) then
			af = dialogs_zaton.zat_b29_af_table[i]
			break
		end
	end

	if (not has_alife_info("zat_b29_linker_take_af_from_rival") and has_alife_info("zat_b29_stalkers_rivals_found_af")) then
		if has_alife_info("zat_b29_stalker_rival_1_found_af") then
			if not has_alife_info("zat_b29_first_rival_taken_out") then
				if has_alife_info("zat_b29_exclusive_conditions") then
					target_obj_id = "zat_b29_stalker_rival_1"
				else
					target_obj_id = "zat_b29_stalker_rival_default_1"
				end
			elseif af == nil then
				if has_alife_info("zat_b29_exclusive_conditions") then
					target_obj_id = "zat_b29_stalker_rival_1"
				else
					target_obj_id = "zat_b29_stalker_rival_default_1"
				end
			end
		elseif has_alife_info("zat_b29_stalker_rival_2_found_af") then
			if not has_alife_info("zat_b29_second_rival_taken_out") then
				if has_alife_info("zat_b29_exclusive_conditions") then
					target_obj_id = "zat_b29_stalker_rival_2"
				else
					target_obj_id = "zat_b29_stalker_rival_default_2"
				end
			elseif af == nil then
 				if has_alife_info("zat_b29_exclusive_conditions") then
					target_obj_id = "zat_b29_stalker_rival_2"
				else
					target_obj_id = "zat_b29_stalker_rival_default_2"
				end
			end
		end
		return get_story_object_id(target_obj_id)
	end

	if af ~= nil then
		return get_story_object_id(target_obj_id)
	end

	return nil
end

function surge_task_target(id, field, p)
	return surge_manager.get_task_target()
end

--AtmosFear Fallout

function fallout_task_title(id, field, p)
	return fallout_manager and fallout_manager.get_task_title() or ""
end

function fallout_task_descr(id, field, p)
	return fallout_manager and fallout_manager.get_task_descr() or ""
end

function fallout_task_target(id, field, p)
	return fallout_manager and fallout_manager.get_task_target() or nil
end

--AtmosFear Psi Storm

function psi_storm_task_title(id, field, p)
	return psi_storm_manager and psi_storm_manager.get_task_title() or ""
end

function psi_storm_task_descr(id, field, p)
	return psi_storm_manager and psi_storm_manager.get_task_descr() or ""
end

function psi_storm_task_target(id, field, p)
	return psi_storm_manager and psi_storm_manager.get_task_target() or nil
end

-----------------------------------------
function kill_strelok(id,field,p)
	local squad = get_story_squad("legendary_strelok")
	if (squad) then
		return squad.id
	end
end
