--'*************************************************************************************
--' Дескриптор обычного задания
--'*************************************************************************************
local guiders_by_level = {
							["zaton"]={["jupiter"]="zat_b215_stalker_guide_zaton", ["pripyat"]="zat_b215_stalker_guide_zaton"},
							["jupiter"]={["zaton"]="zat_b215_stalker_guide_jupiter", ["pripyat"]="jup_b43_stalker_assistant"},
							["pripyat"]={["zaton"]="jup_b43_stalker_assistant_pri", ["jupiter"]="jup_b43_stalker_assistant_pri"},
						 }
function get_guider(target_level)
	local ln = level.name()
	if(guiders_by_level[ln] and guiders_by_level[ln][target_level]) then
		return get_story_object_id(guiders_by_level[ln][target_level])
	end
	return nil
end

local valid_values = {
	complete 	= true,
	fail 		= true,
	reversed 	= true
}

--[[
C++ class task {
		const additional = 1;
		const completed = 2;
		const fail = 0;
		const in_progress = 1;
		const insignificant = 2;
		const storyline = 0;
		const task_dummy = 65535;
};
]]

local status_by_id = {
	[0] = "normal",
	[1] = "selected",
	[2] = "completed",
	[3] = "fail",
	[4] = "reversed"
}

local id_by_status = {
	normal 		= 0,
	selected	= 1,
	completed	= 2,
	fail		= 3,
	reversed	= 4
}

class "CGeneralTask"
function CGeneralTask:__init(task_ini, id)
	self.task_ini = task_ini

	self.id				= id

	self.title			= utils.cfg_get_string(task_ini, id, "title", nil, false, "", "TITLE_DOESNT_EXIST")
	self.title_functor	= utils.cfg_get_string(task_ini, id, "title_functor", nil, false, "", "condlist")
	self.current_title = nil

	self.descr			= utils.cfg_get_string(task_ini, id, "descr", nil, false, "", "DESCR_DOESNT_EXIST")
	self.descr_functor	= utils.cfg_get_string(task_ini, id, "descr_functor", nil, false, "", "condlist")
	self.current_descr = nil

	self.target			= utils.cfg_get_string(task_ini, id, "target", nil, false, "", "DESCR_DOESNT_EXIST")
	self.target_functor	= utils.cfg_get_string(task_ini, id, "target_functor", nil, false, "", "target_condlist")
	self.current_target = nil

	self.icon			= utils.cfg_get_string(task_ini, id, "icon", nil, false, "", "ui_pda2_mtask_overlay")
	self.prior			= utils.cfg_get_number(task_ini, id, "prior", nil, false, 0)
	self.storyline		= utils.cfg_get_bool(task_ini, id, "storyline", nil, false, true)

	--' Условия выполнения и провала квеста
	local i = 0
	self.condlist = {}
	while task_ini:line_exist(id, "condlist_"..i) do
		self.condlist[i] = xr_logic.parse_condlist(nil, "task_manager", "condlist", task_ini:r_string(id, "condlist_"..i))
		i = i + 1
	end

	--' Кондлисты на статусы квеста
	self.on_init = xr_logic.parse_condlist(nil, "task_manager", "condlist", utils.cfg_get_string(task_ini, id, "on_init", nil, false, "", ""))
	self.on_complete = xr_logic.parse_condlist(nil, "task_manager", "condlist", utils.cfg_get_string(task_ini, id, "on_complete", nil, false, "", ""))
	self.on_reversed = xr_logic.parse_condlist(nil, "task_manager", "condlist", utils.cfg_get_string(task_ini, id, "on_reversed", nil, false, "", ""))

	--' Награды за квест
	self.reward_money = xr_logic.parse_condlist(nil, "task_manager", "condlist", utils.cfg_get_string(task_ini, id, "reward_money", nil, false, "", ""))
	self.reward_item = xr_logic.parse_condlist(nil, "task_manager", "condlist", utils.cfg_get_string(task_ini, id, "reward_item", nil, false, "", ""))

	self.community_relation_delta_fail = utils.cfg_get_number(task_ini, id, "community_relation_delta_fail", nil, false, 0)
	self.community_relation_delta_complete = utils.cfg_get_number(task_ini, id, "community_relation_delta_complete", nil, false, 0)

	--' Статус квеста, может быть: "normal", "selected", "completed", "fail", "reversed"
	self.status = "normal"

	self.cached_condlist = {} -- MTB-marek.siemieniuk: cached condlist

	self.current_title = task_functor[self.title_functor](self.id, "title", self.title, self.cached_condlist) -- MTB-marek.siemieniuk: cached condlist
	self.current_descr = task_functor[self.descr_functor](self.id, "descr", self.descr, self.cached_condlist) -- MTB-marek.siemieniuk: cached condlist

	local time = 0
	if self.wait_time ~= nil then
		time = self.wait_time  -- Тут время задано в игровых секундах
	end
	if(self.storyline) then
			if time == 0 then
					self.spot = "storyline_task_location"
		else
					self.spot = "storyline_task_location_complex_timer"
		end
	else
			if time == 0 then
					self.spot = "secondary_task_location"
			else
					self.spot = "secondary_task_location_complex_timer"
			end
	end
	self.current_target = task_functor[self.target_functor](self.id, "target", self.target, self.cached_condlist) -- MTB-marek.siemieniuk: cached condlist
	self.dont_send_update_news = utils.cfg_get_bool(task_ini, id, "dont_send_update_news", nil, false, false)
end
--' Выдача квеста
function CGeneralTask:give_task(community)
	local t = CGameTask()
	t:set_id(tostring(self.id))
	if(self.storyline) then
		t:set_type(task.storyline)
	else
		t:set_type(task.additional)
	end
	t:set_title(self.current_title)
	t:set_description(self.current_descr)
	t:set_priority(self.prior)
	t:set_icon_name(self.icon)
	t:add_complete_func("task_manager.task_complete")
	t:add_fail_func("task_manager.task_fail")

	xr_logic.pick_section_from_condlist(db.actor, db.actor, self.on_init)

	if self.current_target ~= nil then
		t:set_map_location(self.spot)
		t:set_map_object_id(self.current_target)

		if(self.storyline) then
			level.map_add_object_spot(self.current_target, "ui_storyline_task_blink", "")
		else
			level.map_add_object_spot(self.current_target, "ui_secondary_task_blink", "")
		end
	end
	local time = 0
	if self.wait_time ~= nil then
		time = self.wait_time  -- Тут время задано в игровых секундах
	end
	--' Заносим в task_info
	self.status = "selected"
	self.inited_time = game.get_game_time()

	db.actor:give_task(t, time*10, false, time)
	self.t = t
end
--' Проверка текущего выполнения квеста
function CGeneralTask:check_task(tm)
	local global_time = time_global()
	local task_updated = false
	if self.check_time ~= nil and
		 self.last_check_task ~= nil and
		 global_time - self.check_time <= 50
	then
		--' Возвращаем результат прошлой проверки (для оптимизации)
		return
	end
	if self.t == nil then
		self.t = db.actor and db.actor:get_task(self.id, true)
		return
	end

	self.check_time = global_time

	local t_tile = task_functor[self.title_functor](self.id, "title", self.title, self.cached_condlist) -- MTB-marek.siemieniuk: cached condlist
	if self.current_title ~= t_tile then
		printf("task [%s] updated due to title change from [%s] to [%s]", tostring(self.id), tostring(self.current_title), tostring(t_tile))
		task_updated = true
		self.current_title = t_tile
		self.t:set_title(game.translate_string(t_tile))
	end

	local t_descr = task_functor[self.descr_functor](self.id, "descr", self.descr, self.cached_condlist) -- MTB-marek.siemieniuk: cached condlist
	if self.current_descr ~= t_descr then
		printf("task [%s] updated due to description change from [%s] to [%s]", tostring(self.id), tostring(self.current_descr), tostring(t_descr))
		task_updated = true
		self.current_descr = t_descr
		self.t:set_description(game.translate_string(t_descr))
	end

	local t_target = task_functor[self.target_functor](self.id, "target", self.target, self.cached_condlist) -- MTB-marek.siemieniuk: cached condlist
	self:check_level(t_target)
	if self.current_target ~= t_target then
		printf("task [%s] updated due to target change from [%s] to [%s]", tostring(self.id), tostring(self.current_target), tostring(t_target))
		if self.current_target == nil then
			task_updated = true
			self.t:change_map_location(self.spot, t_target)
			if(self.storyline) then
				level.map_add_object_spot(t_target, "ui_storyline_task_blink", "")
			else
				level.map_add_object_spot(t_target, "ui_secondary_task_blink", "")
			end
		else
			if t_target == nil then
				self.t:remove_map_locations(false)
				task_updated = true
			else
				if(self.storyline) then
					level.map_add_object_spot(t_target, "ui_storyline_task_blink", "")
				else
					level.map_add_object_spot(t_target, "ui_secondary_task_blink", "")
				end
				self.t:change_map_location(self.spot, t_target)
				task_updated = true
			end
		end
		self.current_target = t_target
	end
	if task_updated and not(self.dont_send_update_news) then
		news_manager.send_task(db.actor, "updated", self.t)
	end
	for k,v in pairs(self.condlist) do
		local t = xr_logic.pick_section_from_condlist(db.actor, db.actor, v)
		if t ~= nil then
			--' Проверка на валидность
			if valid_values[t] ~= true then
				abort("Invalid task status [%s] for task [%s]", t, self.name)
			end
			self.last_check_task = t
			return
		end
	end

end

--' Инициализация награды
function CGeneralTask:give_reward()
	xr_logic.pick_section_from_condlist(db.actor, db.actor, self.on_complete)

	local money = xr_logic.pick_section_from_condlist(db.actor, db.actor, self.reward_money)
	local items = xr_logic.pick_section_from_condlist(db.actor, db.actor, self.reward_item)

	-- Награду можно выдать двумя методами: от нпс или просто свалитьс неба. Если не найден НПС, с которым мы в диалоге, то просто валим с неба

	local npc = inventory_upgrades.victim

	if money ~= nil then
		dialogs.relocate_money(npc, tonumber(money), "in")
	end

	if items ~= nil then
		local ancillary_item_table = {}
		for k,v in pairs(utils.parse_names(items)) do
			if ancillary_item_table[v] == nil then
				ancillary_item_table[v] = 1
			else
				ancillary_item_table[v] = ancillary_item_table[v] + 1
			end
		end
		for k,v in pairs(ancillary_item_table) do
			dialogs.relocate_item_section(npc, k, "in", v)
		end
	end

end
function CGeneralTask:reverse_task()
	self.last_check_task = "reversed"
end
--' Деактивация квеста
function CGeneralTask:deactivate_task(task)
	printf("deactivate task %s", self.id)

	self.check_time = nil
	if self.last_check_task == "fail" then
		news_manager.send_task(db.actor, "fail", task)
	elseif self.last_check_task == "reversed" then
		xr_logic.pick_section_from_condlist(db.actor, db.actor, self.on_reversed)
		news_manager.send_task(db.actor, "reversed", task)
	end
	self.last_check_task = nil

	self.status = "normal"
end
function CGeneralTask:check_level(target)
	if not(db.actor:is_active_task(self.t)) or not(target) then
		return
	end
	if not(level) then
		return
	end
	local s_obj = alife():object(target)
	if(s_obj) then
		local target_level = alife():level_name(game_graph():vertex(s_obj.m_game_vertex_id):level_id())
		local level_name = level.name()
		if(level_name~=target_level) then
			local guider_id = get_guider(target_level)
			if not(guider_id) then
				return
			end
			local guider_spot = ""
			local guider_spot2 = ""
			if(self.storyline) then
				guider_spot = "storyline_task_on_guider"
				guider_spot2 = "secondary_task_on_guider"
			else
				guider_spot = "secondary_task_on_guider"
				guider_spot2 = "storyline_task_on_guider"
			end
			if(level.map_has_object_spot(guider_id, guider_spot2)~=0) then
				level.map_remove_object_spot(guider_id, guider_spot2)
			end
			if(guider_id and level.map_has_object_spot(guider_id, guider_spot)==0) then
				level.map_add_object_spot(guider_id, guider_spot, "")
			end
		else
			self:remove_guider_spot()
		end
	end
end
function CGeneralTask:remove_guider_spot(target)
	if not(guiders_by_level[level.name()]) then
		return
	end
	for k,v in pairs(guiders_by_level[level.name()]) do
		local guider_id = get_story_object_id(v)
		if(guider_id) then
			if(level.map_has_object_spot(guider_id, "storyline_task_on_guider")~=0) then
				level.map_remove_object_spot(guider_id, "storyline_task_on_guider")
			end
			if(level.map_has_object_spot(guider_id, "secondary_task_on_guider")~=0) then
				level.map_remove_object_spot(guider_id, "secondary_task_on_guider")
			end
		end
	end
end
-- Save quest
function CGeneralTask:save(packet)
	set_save_marker(packet, "save", false, "CGeneralTask")
	packet:w_u8(id_by_status[self.status])
	utils.w_CTime(packet, self.inited_time)
	packet:w_stringZ(self.current_title)
	packet:w_stringZ(self.current_descr)
	packet:w_stringZ(tostring(self.current_target))
	set_save_marker(packet, "save", true, "CGeneralTask")
end
-- Load quest
function CGeneralTask:load(packet)
	set_save_marker(packet, "load", false, "CGeneralTask")
	self.status = status_by_id[packet:r_u8()]
	self.inited_time = utils.r_CTime(packet)
	self.current_title = packet:r_stringZ()
	self.current_descr = packet:r_stringZ()
	self.current_target = packet:r_stringZ()
	if self.current_target == "nil" then
		self.current_target = nil
	else
		self.current_target = tonumber(self.current_target)
	end

	set_save_marker(packet, "load", true, "CGeneralTask")
end
