--[[------------------------------------------------------------------------------------------------------------------
Игнорирование врагов
Чугай Александр
--------------------------------------------------------------------------------------------------------------------]]
local ignored_smart = {
	zat_stalker_base_smart	= true,
	jup_b41					= true,
	jup_a6					= true,
	pri_a16					= true
}

fighting_with_actor_npcs = {
}

local smarts_by_no_assault_zones = {
									["zat_a2_sr_no_assault"] 	= "zat_stalker_base_smart",
									["jup_a6_sr_no_assault"] 	= "jup_a6",
									["jup_b41_sr_no_assault"] 	= "jup_b41"
}


function is_enemy(obj, enemy, st, not_check_sim)
	if not obj:alive() then
		return false
	end

	if obj:critically_wounded() then
		return true
	end

	if st.enabled == false then
		return true
	end

	local overrides = st.overrides
	local obj_id = obj:id()
	local storage = db.storage[obj_id]
	if storage == nil then
		return true
	end
	storage.enemy_id = enemy:id()

	--' Отсеиваем по зоне
	local active_sector = storage.active_sector
	if active_sector ~= nil then
		if sr_danger.check_danger_position(enemy:position(), active_sector) == false then
--			obj:enable_memory_object( enemy, false )
			return false
		end
	end

	-- Проверка на зоны комбат игнора возле баз:
		-- игнорировать если:
		-- враг не актер.
		-- сталкер находится в зоне.
		-- смарт в котором находится сталкер не в состоянии тревоги.
	if db.actor and enemy and enemy:id() ~= db.actor:id() then
		for k,v in pairs (smarts_by_no_assault_zones) do
			local zone = db.zone_by_name[k]
			if zone and (utils.npc_in_zone(obj, zone) or utils.npc_in_zone(enemy, zone)) then
				local smart = sim_board.get_sim_board():get_smart_by_name(v)
				if smart and smart.base_on_actor_control ~= nil and smart.base_on_actor_control.status ~= smart_terrain_control.ALARM then
					return false
				end
			end
		end
	end

	local se_enemy = alife():object(enemy:id())
	if se_enemy ~= nil and se_enemy.m_smart_terrain_id ~= nil and se_enemy.m_smart_terrain_id ~= 65535 then
		local enemy_smart = alife():object(se_enemy.m_smart_terrain_id)
		local smart_name = enemy_smart:name()
		if ignored_smart[smart_name] == true then
--			obj:enable_memory_object( enemy, false )
			return false
		end
	end
	--printf("checking combat_ignore for stalker[%s] enemy name [%s] in section[%s]",obj:name(), enemy:name(),storage.active_section)
	--' Если есть оверрайды, то работаем по ним.
	if overrides and
		 overrides.combat_ignore
	then
		local ret_value = xr_logic.pick_section_from_condlist( enemy, obj, overrides.combat_ignore.condlist )
		if ret_value == "true" then
			--printf("pl:Disabling_memory_object[1] for stalker[%s] enemy name [%s] in section[%s]",obj:name(), enemy:name(),storage.active_section)
--			obj:enable_memory_object( enemy, false )
			return false
		end
		return true
	end
	return true
end
----------------------------------------------------------------------------------------------------------------------

class "action_process_enemy"

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

function action_process_enemy:enemy_callback( obj, enemy )
--'	local obj_pos = self.object:position()
--'	local ene_pos = enemy:position()
--'	printf("FOUND ENEMY [%s](%s,%s,%s) -> [%s](%s,%s,%s)", self.object:name(), obj_pos.x, obj_pos.y, obj_pos.z,
--'														   enemy:name(), ene_pos.x, ene_pos.y, ene_pos.z)
	if enemy:id() == db.actor:id() then
		fighting_with_actor_npcs[obj:id()] = true
	end

	local is_obj_enemy = is_enemy( obj, enemy, self.st, false )
	if is_obj_enemy == true then
		local se_obj = alife():object(obj:id())
		if se_obj and se_obj.m_smart_terrain_id ~= 65535 then
			local smart_obj = alife():object(se_obj.m_smart_terrain_id)
			smart_obj:set_alarm()

			if db.actor and enemy and enemy:id() == db.actor:id() and smart_obj.base_on_actor_control ~= nil then
				-- Fix start for detecting attacking of the base even when attacked npc is not near the base
				local base_pos = db.zone_by_name[smart_obj.base_on_actor_control.noweap_zone]:position()
				local distance = obj:position():distance_to(base_pos)
				if distance < 100 then
					smart_obj.base_on_actor_control:actor_attack()
				end
				-- Fix end for detecting attacking of the base even when attacked npc is not near the base
			end
		end
		local se_enemy			= alife():object(enemy:id())
		if se_obj and se_enemy then
			local sim_obj_registry 	= simulation_objects.get_sim_obj_registry()
			if 	se_obj.group_id ~= 65535 	and sim_obj_registry.objects[se_obj.group_id] ~= nil and
				se_enemy.group_id ~= 65535 	and sim_obj_registry.objects[se_enemy.group_id] == nil and
				se_obj.position:distance_to_sqr(se_enemy.position) > 900 then
				return false
			end
		end
	end

	return is_obj_enemy
end

function action_process_enemy:hit_callback(obj, amount, local_direction, who, bone_index)
	if who == nil then
		return
	end

--	printf("_bp: action_process_enemy: hit_callback(): obj='%s'", obj:name())
	if amount == 0 then
		-- Кто-то стрельнул в воздух
		return
	end

	if who:id() == db.actor:id() then
		local overrides = self.st.overrides
		if not overrides or not overrides.combat_ignore_keep_when_attacked then
			--printf("_bp: action_process_enemy: hit_callback(): obj='%s': SCHEME DISABLED", obj:name())
			self.st.enabled = false
		end
	end
end

----------------------------------------------------------------------------------------------------------------------
-- binder
----------------------------------------------------------------------------------------------------------------------
function add_to_binder( npc, ini, scheme, section, storage )
	local new_action = this.action_process_enemy( npc, storage )
	storage.action = new_action
end

function set_combat_ignore_checker( npc, ini, scheme)
	local st = xr_logic.assign_storage_and_bind( npc, ini, scheme )
end

function reset_combat_ignore_checker(npc, scheme, st, section)
	local storage = st.combat_ignore

	npc:set_enemy_callback( storage.action.enemy_callback, storage.action )

	-- Подписываемся на hit callback-и:
	xr_logic.subscribe_action_for_events( npc, storage, storage.action )

	storage.overrides = xr_logic.generic_scheme_overrides(npc)

	storage.enabled = true
end



function disable_scheme( npc, scheme )
	npc:set_enemy_callback()

	-- Отписываемся от hit callback. Это делать обязательно, потому что иначе при переключении на другой набор
	-- схем, в котором нет перехвата боя, продолжится вызываться callback в старом подписанном action-е.
	local st = db.storage[npc:id()][scheme]
	if st then
		xr_logic.unsubscribe_action_from_events(npc, st, st.action)
	end
end
