----------------------------------------------------------------------------------------------------
-- 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 ()
  if actor_need_help and actor_need_help.obj_id_in_team(self.object:id()) then
  -- —в®Ўл ­Ґ Їлв «бп е®¤Ёвм Ї® Ї ваг«м­л¬ Їгвп¬ б ¤агЈ®Ј® га®ў­п
    return false
  end
  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