----------------------------------------------------------------------------------------------------
-- Sleeper
----------------------------------------------------------------------------------------------------
-- Разработчик: Руслан Диденко (Stohe)
----------------------------------------------------------------------------------------------------
-- 27.12.2004 - [Zmey] Перевел схему на использование move manager.

local sounds = {}

local state_walking = 0
local state_sleeping = 1

---------------------------------------------------------------------------------------------------------------------
--Evaluators
----------------------------------------------------------------------------------------------------------------------
-- Константа
class "evaluator_need_sleeper" (property_evaluator)
function evaluator_need_sleeper:__init(name, storage) super (nil, name)
	self.st = storage
end

function evaluator_need_sleeper:evaluate ()
	--// xr_companion
	if xr_companion.is_companion(self.object:id()) then
		return false
	end	
	--// xr_companion
	return xr_logic.is_active(self.object, self.st)
end

----------------------------------------------------------------------------------------------------------------------
--Actions
----------------------------------------------------------------------------------------------------------------------
-- Обычное поведение
class "action_sleeper_activity" (action_base)
function action_sleeper_activity:__init (npc, action_name, storage) super(nil, action_name)
	self.st = storage

	self.move_mgr = db.storage[npc:id()].move_mgr
	self.was_reset  = false
end
function action_sleeper_activity:initialize()
	action_base.initialize(self)
--	self.object:set_node_evaluator()
--	self.object:set_path_evaluator()
	self.object:set_desired_position()
	self.object:set_desired_direction()        
	--self.state = 0

	self:reset_scheme()	
end
function action_sleeper_activity:reset_scheme()
	self.timer = { begin = nil,
	               idle = nil,
                       maxidle = 10,
                       sumidle = 20,
                       random = 50 }

	self.st.signals = {}
	self.state = state_walking
	if self.st.path_walk_info == nil then
		local patrol_main = patrol(self.st.path_main)
		if not patrol_main then
			abort("object '%s': unable to find path_main '%s' on the map",
				self.object:name(), self.st.path_main)
		end

		local num_wayp = patrol_main:count()
		if num_wayp == 1 then
			self.st.path_walk = self.st.path_main
			self.st.path_walk_info = utils.path_parse_waypoints_from_arglist(self.st.path_main,
				1, { 0, "wp00|ret=1" } )
			self.st.path_look = nil
			self.st.path_look_info = nil
		elseif num_wayp == 2 then
			self.st.path_walk = self.st.path_main
			self.st.path_walk_info = utils.path_parse_waypoints_from_arglist(self.st.path_main,
				2, { 1, "wp00" }, { 0, "wp01" } )
			self.st.path_look = self.st.path_main
			self.st.path_look_info = utils.path_parse_waypoints_from_arglist(self.st.path_main,
				2, { 0, "wp00" }, { 1, "wp01|ret=1" } )
		else
			abort("object '%s': path_main '%s' contains %d waypoints, while 1 or 2 were expected",
				self.object:name(), self.st.path_main, num_wayp)
		end
	end

	-- Последний параметр (true) отключает валидацию путей, чтобы не возникало ошибки из-за использования
	-- одноточечного path_walk пути без соответствующего path_look.
	self.move_mgr:reset(self.st.path_walk, self.st.path_walk_info, self.st.path_look, self.st.path_look_info,
		nil, nil, { obj = self, func = self.callback }, true )
	self.was_reset = true
end	
function action_sleeper_activity:activate_scheme()
        self.was_reset = false
end
function action_sleeper_activity:callback(mode, number)
	self.state = state_sleeping

	local position = nil
	if patrol(self.st.path_main):count() == 2 then
		position = patrol(self.st.path_main):point(1)
	end
	
	if self.st.wakeable then
		state_mgr.set_state(self.object, "sit", nil, nil, {look_position = position})
	else
		state_mgr.set_state(self.object, "sleep", nil, nil, {look_position = position})
	end	
	return true
end	
function action_sleeper_activity:execute()
	action_base.execute(self)
	if not self.was_reset then
		self:reset_scheme()
    end
	if self.state == state_walking then
		self.move_mgr:update()
		if self.move_mgr:arrived_to_first_waypoint() then
			if xr_logic.try_switch_to_another_section(self.object, self.st, db.actor) then
				return
			end
		end
		return
	end
	if self.state == state_sleeping then
		if xr_logic.try_switch_to_another_section(self.object, self.st, db.actor) then
			return
		end
		xr_sound.set_sound(self.object, "sleep")
	end
end
function action_sleeper_activity:finalize()
	xr_sound.set_sound(self.object, nil)
	self.move_mgr:finalize()
   	action_base.finalize(self)
end

-- DEBUG
--function action_sleeper_activity:deactivate()
--	printf( "xr_sleeper: action_sleeper_activity: deactivate" )
--end

----------------------------------------------------------------------------------------------------------------------
--Sleeper binder
----------------------------------------------------------------------------------------------------------------------
function add_to_binder(npc, ini, scheme, section, storage)
  	local operators    = {}
  	local properties  = {}

  	local manager = npc:motivation_action_manager()

  	properties["need_sleeper"]   	= xr_evaluators_id.zmey_sleeper_base + 1
	
  	operators["action_sleeper"]   	= xr_actions_id.zmey_sleeper_base + 1

  	-- // evaluators
  	manager:add_evaluator (properties["need_sleeper"],   this.evaluator_need_sleeper  ("sleeper_need_sleep", db.storage[npc:id()].sleeper))

  	local action = this.action_sleeper_activity(npc, "action_sleeper_activity", db.storage[npc:id()].sleeper)
  	action:add_precondition		(world_property(stalker_ids.property_alive,   	true))
	action:add_precondition		(world_property(stalker_ids.property_danger,	false))
  	action:add_precondition    	(world_property(stalker_ids.property_enemy,   	false))
  	action:add_precondition		(world_property(stalker_ids.property_anomaly,false))
  	action:add_precondition    	(world_property(properties["need_sleeper"],   	true))
  	xr_motivator.addCommonPrecondition(action)
 	action:add_effect(world_property(properties["need_sleeper"], false))
  	manager:add_action(operators["action_sleeper"], action)
	
	-- Зарегистрировать все actions, в которых должен быть вызван метод reset_scheme при изменении настроек схемы:
	xr_logic.subscribe_action_for_events(npc, storage, action)

  	action = manager:action(xr_actions_id.alife)
  	action:add_precondition(world_property(properties["need_sleeper"], false))
end

function set_scheme(npc, ini, scheme, section, gulag_name)
	local st = xr_logic.assign_storage_and_bind(npc, ini, scheme, section)
	st.logic     = xr_logic.cfg_get_switch_conditions(ini, section, npc)		
	st.path_main = utils.cfg_get_string(ini, section, "path_main", npc, true,  gulag_name)
	st.wakeable	 = utils.cfg_get_bool(ini, section, "wakeable", npc, false)

	st.path_walk = nil -- Будут инициализированы в reset(), сейчас пути могут быть еще не загружены.
	st.path_walk_info = nil
	st.path_look = nil
	st.path_look_info = nil
end

function is_npc_asleep(npc)
	return db.storage[npc:id()].state_mgr.animstate:state() == "sleep"
end